web-dev-qa-db-ja.com

typescriptの配列から型を抽出するにはどうすればよいですか?

配列の内部型を「抽出」するTypeScriptで型を宣言する方法はありますか?

例:

コードベースにすでに次のようなものがあるとしましょう。

export interface Cache {
    events: Event[],
    users: User[]
}
type CacheType = Event[] | User[];

//or maybe: 
//   type TypeOfProperty = T[keyof T];
//   type CacheType = TypeOfProperty<Cache>; 

私が欲しいのはこれと同等のものです:

type InnerCacheType = Event | User;

しかし、CacheまたはCacheTypeに何かを追加するたびに、手動で再入力する必要はありません。

これはTypescriptで可能ですか?

15

これはTypeScript2.8以降で可能です。 Unpacked<T>型は次のように宣言できます。

type Unpacked<T> = T extends (infer U)[] ? U : T;

今、あなたはすることができます

type InnerCacheType = Unpacked<CacheType>; // Event | User

これは、 ドキュメント で指定されたUnpackedタイプの要約定義です。

10
Ingo Bürk

TypeScript 2.1以降を使用できると仮定しましょう。そうしないと、探しているものを実現する方法がありません。

また、Cacheインターフェイスのすべてのプロパティが配列になることは当然のことです。そうでない場合、あなたの質問は無意味になるので、私もこの仮定をします。

一般的に、CacheTypeは次のように書くことができます

type CacheType = Cache[typeof Cache];

継承されたプロパティを含みます。得られた型はEvent[] | User[]と同等ですが、そのような共用体型から配列コンポーネントを抽出することは不可能です。

解決策は、マップされたタイプを使用することです。あなたが探しているInnerCacheTypeは次のように書くことができます

type InnerCacheType = MappedCacheType[typeof MappedCacheType];

どこ

type MappedCacheType = { [P in keyof Cache]: Cache[P][0]; };

実際、最後のタイプはと同等です

{ events: Event; users: User; }

TypeScriptは元の名前と同じ名前を保持していることに注意してください。

ユースケースを考慮せずに要約すると、配列型Tのコンポーネント型を表現する方法はT[0]です。

3
FstTesla

これは、型クエリでも実現できます。すなわち。

type CacheType = Event[] | User[];

type InnerCacheType = CacheType[number]; // Event | User

TSプレイグラウンド

1
lonewarrior556