这里发生了一些事情。一是TypeScript不明白这一点
Object.values(x).includes(y)
是一个
type guard
y
. 它与编译器试图缩小类型的内置方式不匹配,例如
typeof
,
instanceof
,或
in
user-defined type guard
要表达这种检查方式:
function isPropertyValue<T>(object: T, possibleValue: any): possibleValue is T[keyof T] {
return Object.values(object).includes(possibleValue);
}
declare function onlyAcceptAllowedValues(allowedValue: AllowedValues): void;
declare const v: string;
if (isPropertyValue(AllowedValues, v)) {
onlyAcceptAllowedValues(v); // v is narrowed to AllowedValues; it works!
}
function doSomething(value: string = AllowedValues.LOREM_IPSUM) {
if (!(isPropertyValue(AllowedValues, value)))
value = AllowedValues.LOREM_IPSUM;
// TypeScript/Intellisense still thinks it is `string`
console.log(value);
}
哦,还是不行。
第二件事是:如果你重新分配一个变量的值,TypeScript基本上放弃了它的缩小。编译器花了大量的精力来理解控制流对变量类型的影响,但是
it's not perfect
我们
AllowedValues.LOREM_IPSUM
value
使之成为
AllowedValues
,编译器
gives up
并假定它是其原始的注释类型,即
string
.
处理问题的方法
这
允许值
. 最直接的方法就是让它成为
const
变量,如下所示:
function doSomething(value: string = AllowedValues.LOREM_IPSUM) {
const allowedValue = isPropertyValue(AllowedValues, value) ? value : AllowedValues.LOREM_IPSUM;
console.log(allowedValue);
}
allowedValue
推断为
允许值
价值
如果类型保护成功(在哪一点
价值
是一个
允许值
),或
AllowedValues.LOREM\u IPSUM允许值
如果类型保护失败。不管怎样,
允许值
是一个
允许值
如果你想帮助编译器理解一些东西的话,这就是我建议的修改。希望有帮助。祝你好运!