網站搜尋

如何在 TypeScript 中獲取值的嚴格類型?


例如,我有一個函數簽名如下:

declare function foo<T>(input: T): T;

我希望它能返回輸入對象的嚴格類型,而不需要手動設置模板類型:

const bar = foo({ str: 'foo', bool: true })

bar 的預期類型是:{ str: 'foo', bool: true }

而不是 { str: string; bool: boolean }。

答案#1

從 TypeScript 3.4 開始,寫

const bar = foo({ str: 'foo', bool: true } as const)

答案#2

我非常喜歡 as const 以及它所帶來的功能,問題在於決定是否使用字面類型的是呼叫者,而不是函式本身。這可能會導致 foo 使用者的困惑,人們很可能會忘記加上 as const,當類型不是字面類型時,其他地方可能會出現奇怪的錯誤。

如果我們依賴 TypeScript 通常推斷字面類型的方式,我們可以讓 foo 強制從它的參數推斷字面類型:

declare function foo<
   T extends Record<string, V>, 
   V extends string | boolean | number | symbol | null | undefined | Record<string, V>
>(input: T ): T;

const bar = foo({ str: 'foo', bool: true, o: { bar: "bar", n: 1 } }); 

// const bar: {
//     str: "foo";
//     bool: true;
//     o: {
//         bar: "bar";
//         n: 1;
//     };
// }

上述解決方案適用於巢狀物件,並且在大多數情況下應該能很好地運作,且不需要呼叫方額外加入 as const。此解決方案適用於 3.4 及之前版本。它依賴於 TypeScript 的特性:如果字面量類型被指派給一個受限制為可以作為字面量類型基礎類型的型別參數,TypeScript 將會保留字面量類型。