4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Extract を便利に使って型の推論を補う

Posted at

TypeScript で、特定の型であることが明確なのに推論が効かないことがあります。

type Foo = { value: number };

type TopFooValueType<A extends Foo[]> = A extends [infer F, ...infer _] ? F['value'] : never;

// Type '"value"' cannot be used to index type 'F'.ts(2536)
// F は Foo 型のはずなのにエラーになる。

このようなケースでは、 下記のようにして制約を満たしていることを保証するかもしれません。

type TopFooValueType<A extends Foo[]> = A extends [infer F, ...infer _]
  ? F extends Foo
    ? F['value']
    : never
  : never;

もしくは、再利用できるように次の Must のような型を用意することもできます。

type Must<T, ToBe> = T extends ToBe ? T : never;

type TopFooValueType<A extends Foo[]> = A extends [infer F, ...infer _] ? Must<F, Foo>['value'] : never;

この Must、よく見ると Extract と同じです。

type Extract<T, U> = T extends U ? T : never;

つまり、冒頭の TopFooValueType は次のように書くことができます。

type TopFooValueType<A extends Foo[]> = A extends [infer F, ...infer _] ? Extract<F, Foo>['value'] : never;

type T = TopFooValueType<[{ value: 1 }, { value: 2 }]>; // 1

もし、型の指定が間違っている場合は never になります(never に対しての Lookup は常に never であるため)。

type Bar = { value: string };

type TopFooValueType<A extends Foo[]> = A extends [infer F, ...infer _] ? Extract<F, Bar>['value'] : never;

type T = TopFooValueType<[{ value: 1 }, { value: 2 }]>; // never
4
1
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
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?