簡體   English   中英

Typescript 通用聯合類型

[英]Typescript generic union type

我正在嘗試創建一個簡單的開關 function ,它采用第一個參數,該參數必須是字符串和 object 的聯合,它具有基於第一個參數聯合的鍵並且可以返回任何值。

export const mySwitch = <T extends string>(value: T, possibilities: {[key in T]: any}): any => {
    return possibilities[value];
};

典型用法是

let option: "val1" | "val2" | "val3" = "val1";
// should returns s1
// Impossible should be type-checked as an error since it's not part of the option union type
mySwitch(option, {val1: "s1", val2: "s2", val3: "s3", impossible: "impossible"});

出現我的問題是因為泛型類型T必須是string才能用作 object 鍵。 我不知道你怎么能告訴Tstring的並集。

我試過T extends string沒有成功。

T extends string版本似乎運行良好。 它不允許impossible ,但是您不想禁止它,因為如果參數永遠不能具有該值,那么該選項將無用嗎?:

export const mySwitch = <T extends string>(value: T, possibilities: {[key in T]: any}): any => {
    return possibilities[value];
};


declare let option: "val1" | "val2" | "val3";
mySwitch(option, {val1: "s1", val2: "s2", val3: "s3", impossible: "impossible"}); 

如果您想允許額外的鍵,您可以單獨聲明案例 object (繞過多余的屬性檢查並允許您重用案例對象)


declare let option: "val1" | "val2" | "val3";
const casses = {val1: "s1", val2: "s2", val3: "s3", impossible: "impossible"}
mySwitch(option, casses); 

或者你可以稍微改變你的類型,這樣泛型類型參數就是 object,值將被鍵入為keyof T

export const mySwitch = <T>(value: keyof T, possibilities: T): any => {
    return possibilities[value];
};


declare let option: "val1" | "val2" | "val3";
mySwitch(option, {val1: "s1", val2: "s2", val3: "s3", impossible: "impossible"}); 

另外一個更好的選擇是保留案例 object 的類型,而不是使用any

export const mySwitch = <T, K extends keyof T>(value: K, possibilities: T): T[K] => {
    return possibilities[value];
};


declare let option: "val1" | "val2" | "val3";
mySwitch(option, {val1: 1, val2: "s2", val3: "s3", impossible: false});  // returns string | number

編輯:

如果聯合中不存在可能性,要保留正確的返回類型和錯誤,您可以使用以下命令:

const mySwitch = <T extends Record<K, any>, K extends string>(value: K, possibilities: T & Record<Exclude<keyof T, K>, never>): any => {
    return possibilities[value];
};

let option: "val1" | "val2" | "val3" = (["val1", "val2", "val3"] as const)[Math.round(Math.random() * 2)]
mySwitch(option, {val1: "s1", val2: "s2", val3: "s3" });
mySwitch(option, {val1: "s1", val2: "s2", val3: "s3", impossible: "" }); //err on impossible

請注意,因為 typescript 進行控制流分析,您需要確保option不僅僅是類型作為您分配的實際常量,而不是您指定的類型注釋

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM