我的问题:我的问题的一个最小示例是(typescript play example with the code):
enum Keys { foo = "foo", bar = "bar" }
function getValue<A extends Keys, B>(dict: { [K in A]?: B }, key: A): B | null
{
const result = dict[key]
if (result !== undefined) {
return result
} else {
return null
}
}
Typescript对语句return result
给出以下类型检查错误:
Type 'B | undefined' is not assignable to type 'B | null'.
Type 'undefined' is not assignable to type 'B | null'.
我的问题:为什么上面的示例中的类型保护result !== undefined
不起作用,该如何解决?
我的尝试
result
的类型为{ [K in A]?: B | undefined; }[A]
。但是,我曾期望打字稿能够自动将其缩减为B | undefined
。也许我在A
或dict
的类型声明中有错误,所以打字稿无法减少查找类型... 3.9.0-dev.20200224
中也会发生此错误。typeof(result) !== "undefined"
并没有帮助。 答案 0 :(得分:2)
目前,这似乎是TSC的错误或设计限制。它不能立即将{ [K in A]?: B | undefined; }[A]
减少为B | undefined
,因此您可以将结果强制转换为B | undefined
或将Keys
移出泛型
const enum Keys { foo = "foo", bar = "bar" }
function get<B>(
dict: { [K in Keys]?: B },
key: Keys
): B | null {
const result = dict[key]
if (result !== undefined) {
return result
} else {
return null
}
}
我也建议始终使用const枚举
答案 1 :(得分:1)
我的问题:上面的代码示例中有什么错误,我该如何解决?似乎类型保护结果!== undefined不起作用...
“修复”的一种方法是一致地返回undefined
而不是返回null
。以下内容可用作API,但正如@Austaras正确说的那样,它不能有效地将类型保护中的result
缩小为B
。
function getValueOne<A extends Keys, B>(
dict: { [K in A]?: B },
key: A
): B | undefined {
const result = dict[key]
if (result !== undefined) {
return result; // result is { [K in A]?: B | undefined; }[A]
} else {
return undefined;
}
}
“修复”的另一种方法是使用这样的显式类型:
function getValueToo<A extends Keys, B>(
dict: { [K in A]?: B },
key: A
): B | null {
const result: B | undefined = dict[key];
if (result) {
return result; // result is B
} else {
return null;
}
}
第三种方法可能是我最喜欢的,因为它是三种方法中最通用的一种。我们更改返回类型。
function getValueThree<A extends Keys, B>(
dict: { [K in A]?: B },
key: A
): (typeof dict)[A] {
const result = dict[key]
if (result !== undefined) {
return result;
} else {
return undefined;
}
}