繁体   English   中英

TypeScript:“A 扩展 B”的键入问题

[英]TypeScript: Typing problem with “A extends B”

[编辑 - 结束语]:事实证明,下面的问题主要是一些次优类型的结果,通常你可能没有像我在我的程序中遇到的这样的问题 => 现在有了这些知识,我的问题似乎没有不再有意义(正如其他人已经在下面提到的那样)。


请查看以下 TypeScript 代码片段。 作为B extends A这个c: 8线当然是允许的。 如何更改function f的类型以禁止ab旁边的其他键?

type A = { a: number, b: number }

function f<B extends A>(b: B): void {
}

f({
  a: 3,
  b: 4,
  c: 8 // <- This shall cause a compile error
})

» 演示

PS:当然function f(b: A) {}不是我要找的。 这里的这个例子只是简化了,现实世界的用例要复杂得多……重要的是function f保持通用。


[编辑]:由于我上面的简化引起了一些混乱:请在此处找到一个更复杂的示例,其中对我上面的问题的回答可能会有所帮助(一个虚构的 UI 组件 API):

请查看 Demo-A 中的类型错误。 这将在 Demo-B 中修复。

Demo-A(类型错误)

Demo-B(无类型错误)

但是正如您在 Demo-B 中看到的那样,您现在可以将无效参数添加到组件配置中 - 这不是很好……这就是我提出上述问题的原因。

[编辑-稍后]不是我上面问题的答案,但至少以下对 Demo-B 的修改应该可以按需要工作: Demo-C

行为是设计使然。 TS 是结构类型语言,其中类型兼容性基于子类型化,换句话说,具有所有约束的每个类型都将通过规则。 在您的示例中,值的类型具有所需的所有字段,因此“a”和“b”,因此一切正常。

您没有理由不允许这样的 object 被传递,因为里面的其他字段不应该让您有所作为。 说你扩展意味着说你被允许在像对象这样的组合方面拥有更多的字段。

另外,如果您想要一个子类型,但使用确切的字段,不幸的是,唯一符合您需要的类型是A ,因此 function 签名应该是f(a: A)

并且要清楚,即使使用f(a: A)您也可以传递带有其他字段的值,只有 object 文字将被严格验证。 任何具有更多字段的赋值都可以使用而不会编译器抱怨。 以及我已经描述的原因。

暂无
暂无

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

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