字体判断器不能真正准确地确定何时可以将特定值分配给generic类型.在泛型上有很少的操作,而TypeScrip可以正确地进行"推理".对于大多数操作,它要么将泛型类型视为opaque,不能将任何不相同的类型视为可赋值类型,要么放弃并将泛型类型参数替换为其constraints.在前一种情况下,这是非常严格的,可能会导致误报(安全代码上的错误),而后一种情况最终会过于宽松,并导致假阴性(不安全代码上的错误失败).
前一种情况是发生在
const condition: Partial<T> = {
[pk]: undefined
}; // error!
编译器将Partial<T>
视为大部分不透明的,并且不接受{[pk]: undefined}
作为可能的值,即使对于任何T
应该允许undefined
作为Partial<T>
的任何属性的值(假设您没有启用the --exactOptionalPropertyTypes
compiler option).事实上,如果您将T
更改为某个特定类型,则赋值将成功.但是编译器不能推论undefined
对于一般情况是允许的.这是在microsoft/TypeScript#22229中描述的.如果您希望编译器接受这一点,您应该使用type assertion:
const condition = {
[pk]: undefined
} as Partial<T>;
后一种情况发生在
const condition: Partial<T> = {};
condition[pk] = undefined;
对于泛型T
,编译器将{}
视为可以赋值给Partial<T>
的为数不多的有效类型之一(这必须显式实现),然后当您将其赋值给condition[pk]
时,编译器就松懈了,允许赋值undefined
.这恰好是安全的,但是编译器并没有真正正确地判断它.
这是在第microsoft/TypeScript#30989节中所描述的.类似的情况在这里也发生了:
const compare = <T extends {a: string}>(s: string) => {
const p: Partial<T> = {a: s}; // error
const o: Partial<T> = {};
o.a = s; // okay
}
The p
line gives an error while the o
code accepts it, but in this case it is the error that's correct, because maybe T
will be specified with a type like {a: "x" | "y"}
and calling compare<{a: "x" | "y"}>("z")
will end up trying to assign "z"
to a place that should be "x" | "y"
. See Why can't I return a generic 'T' to satisfy a Partial<T>? for more information about that.
这就是正在发生的事情.编译器不能真正对任意泛型操作进行准确的分析,所以它走捷径.如果它抱怨您知道是安全的东西,您可以使用类型断言来禁止它.
Playground link to code个