gpt4 book ai didi

typescript 通用联合类型

转载 作者:行者123 更新时间:2023-12-03 23:10:40 24 4
gpt4 key购买 nike

我正在尝试创建一个简单的 switch 函数,它采用第一个参数,该参数必须是字符串的联合和一个对象,该对象具有基于第一个参数联合的键并且可以返回任何值。

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以便用作对象键。我不知道你怎么知道 T成为 string的联合.

我试过 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"});

play

如果您想允许额外的键,您可以单独声明 case 对象(绕过多余的属性检查并允许您重用 case 对象)

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

play

或者你可以稍微改变你的类型,这样泛型类型参数是 case 对象,并且值将被输入为 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"});

play

还有一个更好的选择是保留 case 对象的类型而不是使用 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

play

编辑:

如果联合中不存在可能性,要保留正确的返回类型和错误,您可以使用以下命令:
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

play

请注意,因为 typescript 会进行控制流分析,所以您需要确保 option不仅仅是类型作为您分配的实际常量而不是您指定的类型注释

关于 typescript 通用联合类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58014438/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com