【问题标题】:Issue with TypeScript typingTypeScript 输入问题
【发布时间】:2019-08-15 12:23:26
【问题描述】:

请看下面的 TypeScript sn-p。 为什么这不会引发编译错误?这显然不是类型错误吗?我必须更改什么才能使其再次成为类型安全的? 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观看演示

【问题讨论】:

  • 允许是因为{ a: number, b: number }类型与{ a: number }兼容。
  • 不,这是错误的@Paleo
  • 简化为:typescriptlang.org/play/… - 所以它与Partial&lt;T&gt; 或空值无关。
  • 我设法将问题简化为以下情况: const c: { p: { a: number } } | string = { p: { a: 1, b: 2, // 由于某种原因没问题 } } const d: { a: number } | string = { a: 1, b: 2, // ERROR is now detected } 基本上,当您制作嵌套对象时,类型推断会变得很奇怪。这不是我第一次看到类型推断的问题。当您将对象传递给函数时也会发生这种情况。
  • @WayneC 我反对它是重复的:与接口/继承/索引器无关。

标签: typescript types typescript-typings


【解决方案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&lt;P, K&gt; 与您的C&lt;P&gt; 相同,只是P 类型被扩充为明确排除K 中的所有额外属性。然后我们使用辅助函数asC() 来推断K 的类型,给定传入的参数。由于有问题的键嵌套在下一层,我需要一个 KeyofKeyof&lt;T&gt; 类型来从一层下提取键(如果不点击循环类型,你不能在所有级别上都这样做)。

现在显示所需的错误。耶?我猜。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-12-04
    • 2021-08-03
    • 1970-01-01
    • 2021-01-04
    • 1970-01-01
    • 2020-06-27
    • 2012-06-15
    • 1970-01-01
    相关资源
    最近更新 更多