TypeScript:関数

引数とレスポンスの型の指定

function getSayHelloMsg(name:string):string{
    return "Hello,"+name+'!';
}

レスポンスがないことを示す場合は
・・・ :void{

レスポンスが複数の関数

function get3Msgs(tgt_name:string):[msg1:string, msg2:string, msg3:string]{
    return ['msg1'+tgt_name,'msg2'+tgt_name,'msg3'+tgt_name];
}
const [msg1,msg2,msg3] = get3Msgs('fuga');

引数に条件型を使う

function getSayHelloMsg(name:string | number):string{ ・・・

オプション引数

function sayHelloMsg(name?:string, age?:number):void{ ・・・

オプション引数 初期値あり

function sayHelloMsg(name?:string = ‘no name’, age?:number = -1):void{ ・・・

可変長引数

function totalHoge(…data:number[]):number{ ・・・
通常の引数とあわせて使う場合は可変長引数は最後に。

関数を引数に

const fn = (n:number, f:Function):void => { ・・・
※FunctionのみF(大文字)

関数を引数に、さらに関数の型まで指定

const fn = (n:number, f:(n:number)=>number|string):void => { ・・・
※このときの書き方はアロー関数なのね。

関数の戻り値に関数

const fn = (price:number):(n:number)=>number =>{ ・・・
#だんだん読み取りづらくなるが分解すると以下。
const 関数名 = (引数名:型指定):(レスポンス型指定) => {・・・}
const 関数名 = (引数名:型指定):(レスポンスの関数の引数名:型指定) => レスポンスの関数のレスポンス型指定 => {・・・}

クロージャ例

const countup:(n:number)=> void = (() => {
    let cnt = 0;
    return (n:number):void => {
        cnt += n;
        console.log(cnt);
    };
})();
countup(3);
countup(5);

// countup は 数字の引数、戻しのない関数の型指定。
// アロー関数の即時関数で数字の引数、戻しのない関数を戻す

エラー対応

const getNum = (n:number):number => {
    if(n < 0){
        throw Error('負の値です');
    }
    return n;
}
try {
    console.log(getNum(100));
    console.log(getNum(-100));
} catch(e){
    console.log(e.message);
}

総称型(ジェネリクス)

値の型を特定せずに使う。T、U、Vと使うのが慣例みたい。
function 関数名<T>(引数):戻り値
function 関数名<T>(引数名:T):T

function getRnd<T>(values:T[]):T{
    const r = Math.floor(Math.random() * values.length);
    return values[r];
}
const tmp1 = [0,1,2,3,4];
const tmp2 = ['グー','チョキ','パー'];
const tmp3 = [true,false];

console.log(getRnd(tmp1));
console.log(getRnd(tmp2));
console.log(getRnd(tmp3));

ジェネレータ

function* fibo(n:number){
    let n1 = 0;
    let n2 = 1;
    for(let i = 0; i <= n; i++){
        yield n1; // この値がvalueに。
        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);
    // 終わると ob.done が trueになって ob.value が undefined になる
}

Promise

const wait = (ms:number):Promise<number> => new Promise(resolve => setTimeout( ()=> resolve(ms), ms));
// 改行いれて整理すると以下
const wait = (ms:number):Promise<number> => {
    return new Promise( resolve => {
        setTimeout( ()=> {
            resolve(ms)
        }, ms);
    });
};

wait(100).then((ms:number)=>{console.log(ms+'waitok');});

:Promise<number> で resolve として受け取る関数のパラメータを指定している感じになる…
(総称型の使い道としてちょっと??となっている)

ファクトリ関数

type person = {name:string,age:number};
function createPerson(name:string,age:number):person&{print:()=>void}{
    return {
        name,
        age,
        print:()=>{
            console.log(name,age);
        }
    }
}
const p1 = createPerson('namae',10);
p1.print();

#コンストラクタ関数はTypeScriptでは使えない??らしい?
クラスへ続く…。