網站搜尋

TypeScript 類型推斷與查找類型及 switch case


我有以下 TypeScript 代碼:

type Test = {
    a: string;
    b: boolean;
    c: number;
}
const instance: Test = {
    a: 'a',
    b: true,
    c: 2,
}

function getValue<T extends keyof Test>(val: T): Test[T] {
    return instance[val];
}

function setValue<T extends keyof Test>(key: T, value: Test[T]): void {
    instance[key] = value;

    onChangeValue(key, value);
}

function onChangeValue<T extends keyof Test>(key: T, value: Test[T]): void {
    switch (key) {
        case 'a':
            let a: string = value; // why TS won't infer that value must be type Test['a'] ie. string? Is there any way to fix it?
        break;
        case 'b':
            let b: boolean = value;
        break;
        case 'c':
            let c: number = value;
        break
    }
}

let d: number = getValue('c'); // works fine

setValue('a', 'fsdfdsf'); // works fine

所以基本上,我有一些方法,它們接受一個參數,這個參數是物件類型中的鍵,第二個參數是用來設定該鍵對應的值。我在這裡使用了基於傳入鍵值的查找類型。對於返回鍵對應值以及根據鍵設定值的方法來說,它運作得很好。然而,我有第三個函數 onChangeValue,我希望在其中根據鍵參數的類型來識別值參數的類型。為什麼在這裡不起作用?為什麼編譯器無法正確推斷值參數的類型?有沒有辦法解決這個問題,使它在不顯式類型轉換的情況下也能正常運作?

答案#1

正如 @jcalz 在他的評論中指出的,onChangeValue 的類型並不意味著 value 的類型是一個特定的類型。

例如,當你像這樣宣告一個常數 k 時,它的類型會變成 'a' | 'b'。

const k: 'a' | 'b' = true ? 'a' : 'b' as const

然後當你使用 k 呼叫 onChangeValue 時,onChangeValue 將被實例化為 function onChangeValue<'a' | 'b'>(key: 'a' | 'b', value: string | boolean): void。

onChangeValue(k, true);

正如你所見,即使 key 是 'a',value 也可以是 boolean。這就是為什麼編譯器不會在 switch 中縮小 value 的類型。