为什么这段代码可以在打印脚本中运行?指定的类型是Child,但它也允许传递任何超类(Parent)...反之亦然(用子类替换父类).

class Parent {
  constructor(private foo: string) {}

  bar() {
    return this.foo;
  }
}

class Child extends Parent {
  bar() {
    return 'baz';
  }
}

function doSomething(item: Child) {}

doSomething(new Parent('')); // No type error here...

有没有什么办法可以限制这一点,从而引发类型错误?

EDIT:简化示例

EDIT 2:用示例内容填充课程

推荐答案

来自文档:https://www.typescriptlang.org/docs/handbook/type-compatibility.html#starting-out

TypeScrip的 struct 类型系统的基本规则是,如果y至少具有与x相同的成员,则x与y兼容.例如,考虑下面的代码,该代码涉及一个名为Pet的接口,该接口具有名称属性:

interface Pet {
  name: string;
}

let pet: Pet;
// dog's inferred type is { name: string; owner: string; }
let dog = { name: "Lassie", owner: "Rudd Weatherwax" };
pet = dog;

为了判断宠物狗是否可以分配给宠物,编译器判断了宠物狗的每个属性,以在宠物狗中找到对应的兼容属性.在这种情况下,Dog必须有一个名为name的成员,该成员是一个字符串.是这样的,所以允许赋值.

判断函数调用参数时使用相同的赋值规则:

interface Pet {
  name: string;
}

let dog = { name: "Lassie", owner: "Rudd Weatherwax" };

function greet(pet: Pet) {
  console.log("Hello, " + pet.name);
}
greet(dog); // OK

请注意,Dog有一个额外的Owner属性,但这不会产生错误.在判断兼容性时,只考虑目标类型的成员(在本例中为Pet).

此比较过程以递归方式进行,探索每个成员和子成员的类型.

Typescript相关问答推荐

Angular 17 -如何在for循环内创建一些加载?

处理API响应中的日期对象

APP_INITIALIZER—TypeError:appInits不是函数

使用泛型keyof索引类型以在if-condition内类型推断

带下拉菜单的Angular 响应式选项卡

TS如何不立即将表达式转换为完全不可变?

获取一个TypeScrip对象,并将每个属性转换为独立对象的联合

有没有可能产生输出T,它在视觉上省略了T中的一些键?

从route.参数获取值.订阅提供";无法读取未定义";的属性

避免混淆两种不同的ID类型

如何通过属性名在两个泛型数组中找到匹配的对象?

在Thunk中间件中输入额外参数时Redux工具包的打字脚本错误

TypeScrip:使用Cypress测试包含插槽的Vue3组件

在类型脚本中创建显式不安全的私有类成员访问函数

使用强制转换编写打字函数的惯用方法

在打印脚本中将对象类型转换为数组

Route.ts文件中未导出HTTP方法

如何在TypeScript类成员函数中使用筛选后的keyof this?

包含多个不同类构造函数的接口的正确类型?

是否可以使用元组中对象的键来映射类型