網站搜尋

TypeScript 中物件的鍵和值的類型


我有兩組字串值,我想將它們作為一個常數物件從一個對應到另一個。我想根據這個映射生成兩種類型:一個用於鍵,另一個用於值。

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

這些鑰匙夠簡單:

type Keys = keyof typeof KeyToVal;

我在為這些值獲取 編譯時 類型時遇到困難。我本以為其中一個可能有效:

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];

所有這些都只是讓 Values 變成了 string。我也嘗試過將兩個答案調整到「如何在 typescript 中使用查找推斷型別化的 mapValues?」的問題,但要麼我調整錯了,要麼答案根本不適合我的情況。

答案#1

除非符合 GitHub 問題和 PR 中解釋的某些特定條件,或者對字面值使用 const 斷言,否則編譯器會將字串字面值類型擴寬為 string。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"

答案#2

實際上,你應該將 KeyToVal 改成以下宣告:

const KeyToVal = {
    MyKey1: 'myValue1',
    MyKey2: 'myValue2',
} as const; // <----- add the <as const> here

然後創建鍵的類型:

type Keys = keyof typeof KeyToVal;

現在你可以創建這些值的類型:

type ValuesTypes = typeof KeyToVal[Keys];

答案#3

你正在嘗試從對象(可以有任意數量的鍵/值)推斷類型。你可以先嘗試描述這個類型(或者可能更好的是一個接口),然後像這樣推斷鍵和值:

type KeyToObjMap = {
  some: "other",
  more: "somemore",
};

type Keys = keyof KeyToObjMap;

type Values = KeyToObjMap[Keys];

let one: Values = "some";
let two: Values = "other";
let three: Keys = "some";
let four: Values = "somemore";
let five: Keys = "fun";

而且你在 IDE 中會有正確的高亮顯示。

答案#4

不完全一樣,但如果你有一個物件陣列而不是單一物件,那麼你可以提取已知屬性的值來創建一種類型,方法如下:

const keyToValArray = [
  { value: 'myValue1', label: 'myLabel1' },
  { value: 'myValue2', label: 'myLabel2' }
] as const;
type Keys = typeof keyToValArray[number]['value']; // 'myValue1' | 'myValue2'