0
0

More than 1 year has passed since last update.

【TypeScript】 is (型述語: type predicates) について

Posted at

はじめに

タイトルの通り、typeofなどの型ガードに続き、型述語(type predicates)について学んだのでまとめておく。

結論

以下のような引数の型がstringか否かを返す関数があった場合に、test is stringとしている部分が型述語に当たる。
以下で、詳細をまとめる。

function isString(test: any): test is string{
    return typeof test === "string";
}

詳細

型述語の仕様は以下の通りです。

// 関数の返り値がtrueの場合、testがstringであるとTypeScriptは推論する
function isString(test: any): test is string{
    return typeof test === "string";
}

// また別のexample関数に渡されているfooという引数は、この時点ではany型である
function example(foo: any){
        // isString関数の結果がtrueであった場合には、、
    if(isString(foo)){
        console.log("it is a string" + foo);
        // string型の変数fooからlengthは呼び出し可能であるためコンパイルエラーにならない。
        console.log(foo.length); // string function
    }
}

// ランタイムでもエラーなく実行可能
example("hello world");

また、もしfooからtoExponential というメソッドを呼び出した場合は以下の通りコンパイルエラーとなる。

toExponential は数値を指数表記で表した文字列を返すもので、string型には存在しない

function example(foo: any){
    if(isString(foo)){
        console.log("it is a string" + foo);
        console.log(foo.length);
        // toExponential はstring型には存在しない為コンパイルエラーとなる
        console.log(foo.toExponential(2));
    }
}

では、型述語(test is string)でfooがstring型に推論されているif文の外でtoExponential メソッドを呼び出した場合は、コンパイルエラーにはならないが、実際に引数に渡ってきた値がstring型の場合にはtoExponentialメソッドが存在しないのでランタイムエラーとなる。

function example(foo: any){
    if(isString(foo)){
        console.log("it is a string" + foo);
        console.log(foo.length);
    }
    // fooがstringだと推論されているif文の外なのでコンパイルエラーにはならない。
        // が、実際に引数の型がstring型の場合にはtoExponentialメソッドが存在しないので、ここでランタイムエラーとなる。
    console.log(foo.toExponential(2));
}

また、もし以下のようにtest is string(型述語)を使用しない場合、

function isString(test: any): boolean{
    return typeof test === "string";
}

function example(foo: any){
    if(isString(foo)){
        console.log("it is a string" + foo);
        console.log(foo.length);
                 // fooがstringだと推論されているif文の中でtoExponentialメソッドを呼び出してもコンパイルエラーにはならない。
                 // が、やっぱりstring型の引数にはtoExponentialメソッドが存在しないので、ここでランタイムエラーとなる。
        console.log(foo.toExponential(2));
    }
}

おわりに

typeofよりも難しそうに思えたが、色々なケースを見て理解できた。これもエラーを事前に防ぐのに役立ちそうなので積極的に活用していきたい。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0