简体   繁体   English

TypeScript输入问题

[英]Issue with TypeScript typing

Please have a look at the following TypeScript snippet. 请查看以下TypeScript代码段。 Why does that NOT throw a compile error? 为什么不抛出编译错误? Isn't that obviously a type error? 显然不是类型错误吗? What do I have to change to make it type-safe again? 我必须更改什么才能使其再次成为类型安全的? TYVM 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)

Click here for a demo 点击此处进行演示

This is a known bug where excess property checking doesn't apply to nested types involving unions and intersections in the way that people expect. 这是一个已知的错误 ,其中多余的属性检查不适用于人们期望的涉及联合和交集的嵌套类型。 Excess property checking is kind of an add-on to the type system that only applies to object literals, so when it doesn't apply, things fall back to the structural subtyping rule where type {a: A, b: B} is a subtype of {a: A} , and so a value of the former type should be assignable to a variable of the latter type. 多余的属性检查是类型系统的一个附加组件,该类型系统仅适用于对象文字,因此当它不适用时,情况会退回到结构子类型规则,其中类型{a: A, b: B}是a {a: A}子类型,因此前一种类型的值应可分配给后一种类型的变量。 You might want to head over to the issue in Github and give it a 👍 or explain your use case if you think it's more compelling than the ones already listed there. 如果您认为它比此处已列出的问题更具说服力,则可能需要转到Github的问题并给它一个👍或解释您的用例。 Hopefully there will be a fix someday. 希望有一天会修复。

Until then, though, I'm not sure what can be done. 不过在那之前,我不确定该怎么做。 The type-level equivalent to excess property checks are so-called exact types , which don't exist in TypeScript as concrete types. 等同于多余属性检查的类型级别称为精确类型 ,在TypeScript中不作为具体类型存在。 There are ways to simulate them using generic helper functions and type inference... in your case it would look something like this: 有一些方法可以使用通用辅助函数和类型推断来模拟它们……在您的情况下,它看起来像这样:

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
  }
})

Yes, it's ugly. 是的,这很丑。 Not sure if it's worth it to you. 不确定是否值得您这样做。 The way it works is to say that C<P, K> is the same as your C<P> except that the P type is augmented to explicitly exclude all the extra properties in K . 它的工作方式是说C<P, K>与您的C<P>相同,只是增加了P类型以显式排除K所有额外属性。 Then we use the helper function asC() to infer a type for K given the passed-in parameter. 然后,在给定传入参数的情况下,使用辅助函数asC()来推断K的类型。 Since the keys in question are nested one level down, I needed a KeyofKeyof<T> type to extract keys from one level down (you can't do it for all levels without hitting circular types). 由于所讨论的键是向下嵌套一层的,因此我需要一个KeyofKeyof<T>类型来从一级向下提取键(不能在不触及循环类型的情况下对所有级别都进行提取)。

The desired error shows up now. 现在出现所需的错误。 Yay? 好极了? I guess. 我猜。

Anyway hope that helps. 无论如何希望能有所帮助。 Good luck! 祝好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM