1. ホーム
  2. typescript

Typescriptでオブジェクトのキーと値の両方から型を取る

2023-07-08 14:51:41

質問

2つの文字列値のセットがあり、定数オブジェクトとして一方から他方へマッピングしたいのです。 私はそのマッピングから2つの型を生成したい:1つはキー用に、もう1つは値用に。

const KeyToVal = {
    MyKey1: 'myValue1',
    MyKey2: 'myValue2',
};

キーは簡単です。

type Keys = keyof typeof KeyToVal;

を取得するのに苦労しています。 コンパイル時 型を取得するのに苦労しています。 私は多分これらのうちの1つがうまくいくと思った。

type Values = typeof KeyToVal[Keys];
type Values<K> = K extends Keys ? (typeof KeyToVal)[K] : never;
type Prefix<
    K extends Keys = Keys, 
    U extends { [name: string]: K } = { [name: string]: K }
> = {[V in keyof U]: V}[K];

これらはすべて、ただ単に Valuesstring . また、2つの答えを適応してみたところ typescriptでルックアップを使用して型付けされたmapValueを推論する方法は? を適応させようとしましたが、適応を間違えたか、そもそも答えが私のシナリオに合っていなかったかのどちらかです。

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

コンパイラは、文字列リテラルの型を string に広げますが、github で説明されているような特定の条件を満たさない限りは 問題 PR または const アサーション はリテラル値に対して使われる。constアサーションはTypeScript 3.4で登場した。

const KeyToVal = {
    MyKey1: 'myValue1',
    MyKey2: 'myValue2',
} as const;

type Keys = keyof typeof KeyToVal;
type Values = typeof KeyToVal[Keys]; //  "myValue1" | "myValue2"

3.4より前では、同じ効果を得るための回避策がありました。コンパイラにリテラル型を推論させるには、適切に細工された汎用型パラメータを持つ関数を介してオブジェクトを渡す必要がありましたが、これはこの場合のトリックを行うようです。

function t<V extends string, T extends {[key in string]: V}>(o: T): T {return o}

この関数の目的は、型推論を可能にするために型をキャプチャして保持することであり、それ以外は全く意味がありませんが、この関数を使うことで

const KeyToVal = t({
    MyKey1: 'myValue1',
    MyKey2: 'myValue2',
});

type Keys = keyof typeof KeyToVal;
type Values = typeof KeyToVal[Keys]; //  "myValue1" | "myValue2"