请查看以下 TypeScript 片段。 为什么这不会引发编译错误?这不是明显的类型错误吗?我必须更改什么才能使其再次成为类型安全的? TYVM
type A<P> = {
p?: never,
q?: Partial<P>
}
type B<P> = {
p?: Partial<P>
q?: never
}
type C<P> = A<P> | B<P>
const c: C<{ a: number}> = {
p: {
a: 1,
b: 2 // <------ Why is this allowed?!?
}
}
console.log(c)
点击here演示
最佳答案
这是一个 known bug其中 excess property checking不适用于以人们期望的方式涉及并集和交集的嵌套类型。过多的属性检查是类型系统的一种附加组件,它只适用于对象文字,所以当它不适用时,事情会回到 structural subtyping。规则类型 {a: A, b: B}
是 {a: A}
的子类型,因此前一种类型的值应该可以分配给后一种类型的变量。您可能想转到 the issue in Github并给它一个 👍 或解释你的用例,如果你认为它比已经列出的那些更有吸引力。希望有一天会有修复。
不过,在那之前,我不确定能做什么。相当于超额属性(property)检查的类型级别是所谓的exact types ,它们在 TypeScript 中不作为具体类型存在。有一些方法可以使用通用辅助函数和类型推断来模拟它们......在你的情况下它看起来像这样:
type Exactify<T, K extends keyof any>
= T & { [P in Exclude<K, keyof T>]?: never };
type A<P, K extends keyof any=never> = {
p?: never,
q?: Partial<Exactify<P, K>>
}
type B<P, K extends keyof any=never> = {
p?: Partial<Exactify<P, K>>
q?: never
}
type C<P, K extends keyof any = never> = A<P, K> | B<P, K>
type KeyofKeyof<T> =
keyof T | { [K in keyof T]: T[K] extends object ? keyof T[K] : never }[keyof T];
const asC = <T extends C<{ a: number }, KeyofKeyof<T>>>(c: T) => c;
const c = asC({
p: {
a: 1,
b: 2 // <------ error
}
})
是的,它很丑。不确定这对你来说是否值得。它的工作方式是说 C<P, K>
和你的一样C<P>
除了P
type 被扩充以明确排除 K
中的所有额外属性.然后我们使用辅助函数 asC()
推断 K
的类型给定传入的参数。由于有问题的键嵌套了一层,我需要一个 KeyofKeyof<T>
type 从一个级别向下提取键(如果不点击循环类型,你不能对所有级别执行此操作)。
所需的错误现在出现了。好极了?我猜。
无论如何希望对您有所帮助。祝你好运!
关于typescript - TypeScript 输入问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55334784/