【发布时间】:2019-08-06 09:32:38
【问题描述】:
根据文档,“TypeScript 中的类型兼容性基于结构子类型”。所以这是可能的:
type Person: {
name: string;
}
const developer = {
name: 'Joe',
language: 'Typescript',
}
// this is ok because Person is a subtype of typeof developer
const otherDeveloper: Person = developer; // who writes code like that?!
这有很多后果,其中之一是您在使用 Object.keys 时会丢失类型信息:
// "keys" type is array of strings not `name` literal as this would be of course wrong because in runtime "keys" is ['name', 'language']
const keys = Object.keys(otherDeveloper);
所以我试图按照他们的承诺在 TS 文档中找到这种子类型化的原因,但我找不到
仔细考虑了 TypeScript 允许不良行为的地方,在本文档中,我们将解释这些情况发生的位置以及它们背后的动机。
这可能对我有帮助的唯一地方是一个期望更窄类型对象的函数,例如:
function getName(person: Person) {
return person.name;
}
getName(developer); // works fine because of subtyping
如果您在这种情况下必须使用强制转换,我个人认为这不是什么大问题:
getName(developer as Person);
还有其他我可能遗漏的例子吗?
【问题讨论】:
-
嗯,这称为多态性,是所有面向对象语言的基本原则。它基本上模拟了生活的现实。任何人都可以注册一个节目。开发人员是一个人。他/她比“基本”人拥有更多的属性(例如他/她知道的计算语言)。但节目不在乎。它只关心你是否是一个人。
-
如果没有子类型化,什么都不会真正起作用,它是任何面向对象方法的基础,即使在 JS 中,您也经常将具有更多字段的对象传递给仅使用少数字段的函数。奇怪的部分是当 TS 不允许子类型替换基本类型时,例如当它警告过多的属性检查时(
getName( { name: 'Joe', language: 'Typescript', })是一个错误)。过多的属性检查与 OO 相悖,但有助于发现常见错误。 -
@JBNizet 我认为这里所说的问题是没有为
Developer定义明确的子类,但代码仍然适用于developer对象上的额外属性,即使该对象的类型为@987654329 @ 在强类型语言上会失败的东西。 -
@apokryfos 是的 .. 每个 C#/C++/Java 开发人员在迁移到 TS 时都会遇到结构化类型的有趣惊喜。它是强类型的,而不是您认为的强类型。
标签: typescript subtyping structural-typing