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"});
如果你想允许额外的键,你可以单独声明case对象(绕过多余属性检查并允许重用case对象)。
play
declare let option: "val1" | "val2" | "val3";
const casses = {val1: "s1", val2: "s2", val3: "s3", impossible: "impossible"}
mySwitch(option, casses);
播放
或者您可以稍微改变类型,使泛型类型参数成为 case 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"});
播放
此外,更好的选择是保留案例对象中的类型,而不是使用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});
编辑:
为保留正确的返回类型并在联合中存在可能性但未出现错误时,可以使用以下代码:
播放
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: "" });
请注意,由于TypeScript具有控制流分析功能,因此您需要确保
option
不仅仅是您指定的类型注释,而是实际分配的常量。
play
T extends string
的问题是什么?它不允许impossible
(我不确定你是否想要这个),但除此之外它可以正常工作:https://www.typescriptlang.org/play/#code/KYDwDg9gTgLgBAYwgOwM7wLYE8DKB3ASxgQAs4BeOAHgBU5QZhkATVOdKA5AcwD4AKAG4BDADYBXYAC44NADRxIqVAQBGBUUQLBUMgN4BtANbAscLrIC6M4ciwBfAJQ27FXnD0BYAFBw-cKGAYcShkRQhlNQ0tHQMRCWBLAG4fexTvHx9mYARRYUC4USC4CDAYAhQZACJ4gEYquAAfOBqxACYG5tbRAGYq9Ox8IlJ+UvKUBT066tR6hXi2mY75sR6ZvoUCDCUVVSLqrZ21IqqnJLggA - Titian Cernicova-Dragomirval1
是可能的,而不管你的类型注释,所以任何不是val1
的属性都会出现错误。引入一些不确定性,这个例子就可以工作了: - Titian Cernicova-Dragomir