我最近玩过打字稿泛型,发现了我不知道如何解释的行为,在我的恳求下:
具有初始值的枚举列表
几个显示结果的类,一个类恰好对应一个枚举值
所以任务是编写将初始值映射到结果值的函数(简单的 switch 情况),但这对我来说还不够,因为这种情况的类型类似于:
1 个枚举 => 任何结果类
所以我继续使用泛型,创建初始枚举到结果值的类型映射,制作泛型函数,在这种情况下工作正常,类型现在很好:
1 个枚举 => 1 个结果类
但问题是,在这种情况下,打字稿不想识别返回值的类型,因此我将类型转换为任何类型,有一个最小的playground和链接过期时的代码:
enum TestKind {
String = 'str',
Number = 'num',
Boolean = 'bool',
}
type TestKindTypeMap = {
[TestKind.String]: string;
[TestKind.Number]: number;
[TestKind.Boolean]: boolean;
};
function transformerWithBadTyping(input: TestKind): TestKindTypeMap[TestKind] {
switch (input) {
case TestKind.String:
return '';
case TestKind.Number:
return 0;
case TestKind.Boolean:
return false;
default:
throw new Error();
}
}
console.log(transformerWithBadTyping(TestKind.String))
console.log(transformerWithBadTyping(TestKind.Number))
console.log(transformerWithBadTyping(TestKind.Boolean))
function transformer<K extends TestKind>(input: K): TestKindTypeMap[K] {
switch (input) {
case TestKind.String:
return '';
case TestKind.Number:
return 0 as any;
case TestKind.Boolean:
return false as TestKindTypeMap[K];
default:
throw new Error();
}
}
console.log(transformer(TestKind.String))
console.log(transformer(TestKind.Number))
console.log(transformer(TestKind.Boolean))
所以问题是:
Typescript 无法缩小来自泛型参数的类型,解决方法如下:
function transformer<K extends TestKind>(input: K): TestKindTypeMap[K] {
const out : {[K in TestKind]: (input: K) => TestKindTypeMap[K]} = {
[TestKind.String]: () => '',
[TestKind.Number]: () => 0,
[TestKind.Boolean]: () => false
};
return out[input](input);
}