網站搜尋

typescript - 如何根據參數的值在函式內縮小簽名?


我正在嘗試將一個介面的多個方法合併為一個帶有額外 operation 參數的函數。生成的函數可以如預期般被調用,但似乎我無法在函數內縮小簽名類型。這個 SO 問題有些幫助,但編譯器仍然認為在 "plus" 情況下 args[1] 可能是 undefined:

interface Calculator {
    plus: (a: number, b: number) => number;
    unaryPlus: (a: number) => number;
}

type CalculateParameters = {
    [P in keyof Calculator]: [P, ...Parameters<Calculator[P]>];
}[keyof Calculator];

const calculate = (...[operation, ...args]: CalculateParameters) => {
    switch (operation) {
        case "plus":
            // Object is possibly undefined
            return args[0] + args[1];
        case "unaryPlus":
            return args[0];
        default:
            throw new Error("Unknown operation.");
    }
};

// Work as expected
export const x = calculate("plus", 1, 2);
export const y = calculate("unaryPlus", 1);

遊樂場

我按照這裡的建議嘗試了條件類型,但那也需要大量重複以及類型轉換。有沒有可能在 calculate 中縮小簽名而不這樣做?

附註:一旦解決了參數輸入的型別問題,我還會面臨正確輸出返回值型別的問題。Calculator 可能有回傳非 number 的函式,而 calculate 應該能夠反映這一點。

答案#1

你可以選擇:

interface Calculator {
    plus: (a: number, b: number) => number;
    unaryPlus: (a: number) => number;
}

type CalculateParameters = {
    [P in keyof Calculator]: [P, ...Parameters<Calculator[P]>];
}[keyof Calculator];

const calculate = (...args: CalculateParameters) => {
    switch (args[0]) {
        case "plus":
            // Object is possibly undefined
            return args[1] + args[2];
        case "unaryPlus":
            return args[1];
        default:
            throw new Error("Unknown operation.");
    }
};

// Work as expected
export const x = calculate("plus", 1, 2);
export const y = calculate("unaryPlus", 1);

請參見如何根據另一個函數參數縮小後的類型來推斷/縮小函數參數的類型?詳情討論