1. ホーム
  2. typescript

[解決済み] Typescript はタプル/配列の値からユニオン型を導出します。

2022-04-26 13:12:54

質問

リストがあるとします const list = ['a', 'b', 'c']

この値から、次のようなユニオン型を導出することは可能でしょうか? 'a' | 'b' | 'c' ?

私は、静的配列からの値のみを許可する型を定義したいので、これが必要です。また、実行時にこれらの値を列挙する必要があるので、私は配列を使用します。

インデックス付きオブジェクトでの実装例です。

const indexed = {a: null, b: null, c: null}
const list = Object.keys(index)
type NeededUnionType = keyof typeof indexed

インデックス付きマップを使わずにできないかな。

どのように解決するのですか?

UPDATE 2019年2月

2019年3月にリリースされる予定のTypeScript 3.4 のタプルの型を推論するようにコンパイラに指示することができるようになります。 リテラルのタプルとして のようにではなく、例えば string[] を使用することで as const 構文 . このタイプのアサーションは、コンパイラが値に対して可能な限り狭い型を推論するようにし、すべての readonly . このように表示されるはずです。

const list = ['a', 'b', 'c'] as const; // TS3.4 syntax
type NeededUnionType = typeof list[number]; // 'a'|'b'|'c';

これにより、いかなる種類のヘルパー関数も不要になります。 皆さん、また頑張ってください。


UPDATE 2018年7月号

どうやら、TypeScript 3.0から、TypeScriptで 自動的にタプルの型を推論する . リリースされると tuple() の関数は、簡潔に次のように書くことができます。

export type Lit = string | number | boolean | undefined | null | void | {};
export const tuple = <T extends Lit[]>(...args: T) => args;

そして、このように使うことができます。

const list = tuple('a','b','c');  // type is ['a','b','c']
type NeededUnionType = typeof list[number]; // 'a'|'b'|'c'

これでみんなに使ってもらえるといいんだけどなー。


UPDATE 2017年12月

この回答を投稿してから、ライブラリに関数を追加してくれるなら、タプル型を推論する方法が見つかりました。 関数をチェックアウトする tuple() tuple.ts . それを使って、以下のように書くと、繰り返しにならずに済みます。

const list = tuple('a','b','c');  // type is ['a','b','c']
type NeededUnionType = typeof list[number]; // 'a'|'b'|'c'

がんばってください


ORIGINAL 2017年7月号

一つの問題は、リテラル ['a','b','c'] という型として推論されます。 string[] そのため、型システムは特定の値について忘れてしまいます。 各値をリテラル文字列として記憶するよう、型システムに強制することができます。

const list = ['a' as 'a','b' as 'b','c' as 'c']; // infers as ('a'|'b'|'c')[]

あるいは、リストをタプル型として解釈する方がいいかもしれません。

const list: ['a','b','c'] = ['a','b','c']; // tuple

これは迷惑な繰り返しですが、少なくとも実行時に余計なオブジェクトを導入することはありません。

これで、こんな感じでユニオンを取得できます。

type NeededUnionType = typeof list[number];  // 'a'|'b'|'c'.

お役に立てれば幸いです。