为什么 Typescript 允许子类型化?
Why does Typescript allow for subtyping?
根据文档,"Type compatibility in TypeScript is based on structural subtyping"。所以这是可能的:
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 文档中找到这种子类型化的原因,但我找不到
The places where TypeScript allows unsound behavior were carefully considered, and throughout this document we’ll explain where these happen and the motivating scenarios behind them.
这可能对我有帮助的唯一地方是需要较窄类型对象的函数,例如:
function getName(person: Person) {
return person.name;
}
getName(developer); // works fine because of subtyping
如果您在那种情况下必须使用转换,我个人认为没有什么大问题:
getName(developer as Person);
还有其他我可能遗漏的例子吗?
Typescript 使用结构类型的原因是 JS 是 duck 类型的。
所以你可以用 JS 做你上面写的,理想情况下你可以在 TS 中以一种更安全的方式来做。 Javascript不关心对象的声明类型,JS中没有这个概念,它只关心对象在运行时具有的属性。因此,任何对象都可以传递到您的 getName
函数中,只要名称 属性 存在,该函数就可以正常运行。
此外,由于 JS 具有不属于特定 class 的对象字面量,因此很难在任何地方明确指定继承关系。使类型关系显式会使 TS 对 JS 开发人员的吸引力降低。在结构类型系统下,类型大部分都在我们的范围内工作,您可以从中获益良多,而不必非常明确。
有一些方法可以通过使用私有属性 () or using branded types ()
绕过结构类型并在打字稿中模仿规范类型
根据文档,"Type compatibility in TypeScript is based on structural subtyping"。所以这是可能的:
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 文档中找到这种子类型化的原因,但我找不到
The places where TypeScript allows unsound behavior were carefully considered, and throughout this document we’ll explain where these happen and the motivating scenarios behind them.
这可能对我有帮助的唯一地方是需要较窄类型对象的函数,例如:
function getName(person: Person) {
return person.name;
}
getName(developer); // works fine because of subtyping
如果您在那种情况下必须使用转换,我个人认为没有什么大问题:
getName(developer as Person);
还有其他我可能遗漏的例子吗?
Typescript 使用结构类型的原因是 JS 是 duck 类型的。
所以你可以用 JS 做你上面写的,理想情况下你可以在 TS 中以一种更安全的方式来做。 Javascript不关心对象的声明类型,JS中没有这个概念,它只关心对象在运行时具有的属性。因此,任何对象都可以传递到您的 getName
函数中,只要名称 属性 存在,该函数就可以正常运行。
此外,由于 JS 具有不属于特定 class 的对象字面量,因此很难在任何地方明确指定继承关系。使类型关系显式会使 TS 对 JS 开发人员的吸引力降低。在结构类型系统下,类型大部分都在我们的范围内工作,您可以从中获益良多,而不必非常明确。
有一些方法可以通过使用私有属性 (