[TypeScript] 高度な関数

### 例外処理
try, catch(e), finallyで書く
以下のスクリプトでは

const f = (arr?:any[]): void => {
    let res = 'Array: '
    for(let i of arr){
        res += String(i) + '\t'
    }
    console.log(res)
}

try {
    f(['ok', 'NG'])
    f([10, 20, 30])
    f()
} catch(e){
    console.log(e.message)
}

“arr is not iterable”

### 例外を発生させる関数

const f = (n:number):[number, Error?] => {
    if (n < 0){
        return [n, Error("negative number")]
    }
    let total = 0
    for(let i = 1; i<= n; i++)
        total += i
    return [total]
}

let[res1, err1] = f(100)
if(err1 == undefined)
    console.log(res1)
else console.log(err1)

let[res2, err2] = f(-100)
if(err2 == undefined)
    console.log(res2)
else console.log(err2)

### Errorをthrowする
throw Error

const f = (n:number):number => {
    if (n < 0){
        throw Error("negative!")
    }
    let total = 0
    for(let i = 1; i<= n; i++)
        total += i
    return total
}

let re1 = f(100)
console.log(re1)
let re2 = f(-100)
console.log(re2)

### ジェネリクス
定義の段階では型を指定せず、利用する場合に特定の型を使う
function 関数 ()引数:戻り値

function getRnd<T>(values: T[ ]): T {
    const r = Math.floor(Math.random() * values.length)
    return values[r]
}

const data1 = [0, 2, 4, 5, 6, 10]
const data2 = ['グー','チョキ','パー']
const data3 = [true, false]

for(let i = 0; i < 10; i++){
    const re1 = getRnd(data1)
    const re2 = getRnd(data2)
    const re3 = getRnd(data3)
    const res = re1 + '(' + typeof(re1) + ')\t'
        + re2 + '(' + typeof(re2) + ')\t'
        + re3 + '(' + typeof(re3) + ')'
    console.log(res)
}

### ジェネレーターと遅延評価
呼び出すごとに新しい値を取り出す関数
function* と yield(待ち状態)を作ります
nextで次の数字を呼び出す

function* fibo(n:number){
    let n1 = 0
    let n2 = 1
    for(let i = 0; i <= n; i++){
        yield n1
        let n3 = n1 + n2
        n1 = n2
        n2 = n3
    }
}

const n = 10
let fb = fibo(n)
for(let i = 0; i <= n + 3; i++){
    let ob = fb.next()
    console.log(ob.value)
}

### 非同期処理とpromise
処理を開始すると、待ち続けることなく次の処理に進んでいく
promiseは事後処理を呼び出して必要な作業を行う

function 関数(引数): Promise {
	return new Promise ((関数) => {


		関数()
	})
}
const f = (n:number, d:number): Promise<number> => {
    console.log("start:" + n)
    return new Promise((f) => {
        let total = 0
        for(let i = 1; i <= n; i++)
            total += i
        setTimeout(() => {
            f(total)
        }, d)
    })
}

const cb = (n:number) => {
    console.log("result:" + n)
}

f(10, 300).then(cb)
f(100, 200).then(cb)
f(1000, 100).then(cb)

プロミスを理解しないといけないことはわかった