• ..

git

    unknown 型

    anyと似ていますがタイプセーフな型です。型を特定するまであらゆる操作が制限されるみたいな型です。unknownは存在しうるすべての型の Union のようなものかなと思います。(anyも)

    const foo: unknown = 'foo';
    // これは以下のようなもの(`IDO5`などは適当)
    const foo: IDO5 | n0lM | 'sowe' | ... | string | number | boolean | undefined | null = 'foo'

    上記では'foo'を入れていますが、これは Union にstringもしくは'foo'型が含まれる(イメージ)ので代入することができます。

    ですがunknownの特徴として、unknownのままではプロパティやプロトタイプメソッドなどすべてのアクセスが制限されてしまいます。

    const a: unknown = 'a';
    a.foo
    // Object is of type 'unknown'.

    型を特定する

    そのまま使えるのならそのままでいいかもしれないですが、unknownで何かしようと思ったら使う前にまず型変換してあげる必要があります。

    例えばstring | undefinedという型valueの時、if (value !== undefined) {...}とすることで...ではvaluestring型だということに絞り込むことができます。

    「存在しうるすべての型の Union のようなもの」と言ったようにunknown肯定的if文などで特定の型にキャストすることができます。また他の同じようにtypeofinstanceof,inなどを使った絞り込みも効いてくれます。

    例えば以下のようにunknown型をstringに絞り込めます。

    const a: unknown = 'a';
    // const a: unknown
    if (typeof a === 'string') {
      // const a: string
    }

    タイプガードの場合。これはFooBarに絞り込みます。

    interface Foo {
      foo: string;
    }
    interface Bar {
      bar: string;
    }
    
    const isFoo = (value: unknown): value is Foo => {
      return typeof value === 'object' && typeof (value as Foo).foo === 'string';
    }
    
    const isBar = (value: unknown): value is Bar => {
      return typeof value === 'object' && typeof (value as Bar).bar === 'string';
    }
    
    
    const a: unknown = {};
    if (isFoo(a)) {
      // const a: Foo
    } else if (isBar(a)) {
      // const a: Bar
    }

    使い所

    1. APIから返ってくるような外部のデータ
    2. 種類が多い({type: ...}みたいな)
    3. 1回のAPIにすべての種類が含まれている訳ではない

    みたいな所とかは受け取った直後に一旦unknownで置いておいて、キャストする為の関数みたいなところに渡すとコードがスッキリするかなと思います。

    あと最近だと強制型変換などで一旦unknownに置いてから目当ての型に再度変換するというのもあります。

    const a: Foo = {...};
    (a as unknown) as Bar