TypeScript输入问题

时间:2019-03-25 09:32:48

标签: typescript types typescript-typings

请查看以下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进行演示

1 个答案:

答案 0 :(得分:1)

这是known bug,其中excess property checking不适用于人们期望的涉及联合和交集的嵌套类型。多余的属性检查是类型系统的一个附加组件,它仅适用于对象文字,因此当它不适用时,情况会退回到structural subtyping规则中,其中类型{a: A, b: B}是子类型{a: A}的值,因此前一种类型的值应可分配给后一种类型的变量。如果您认为此案例比已经列出的案例更具吸引力,那么您可能想要转到the issue in Github并给出一个案例或解释您的用例。希望有一天会解决此问题。

不过,直到那时,我不确定该怎么做。等同于多余属性检查的类型级别称为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类型以明确排除K中的所有其他属性。然后,根据给定的传入参数,使用辅助函数asC()来推断K的类型。由于有问题的键是向下嵌套一级的,因此我需要一种KeyofKeyof<T>类型的键才能从一级向下提取键(不能在不触及循环类型的情况下对所有级别都进行此操作)。

现在出现所需的错误。好极了?我想。

无论如何,希望能有所帮助。祝你好运!