Skip to content

结构化类型

Typescript 的对象类型表示对象的结构。这是一种设计选择,JavaScript 采用的是结构化类型,Typescript 直接沿用,没有采取名义化类型

结构化类型中,类型的兼容性是根据其结构或成员来确定的,而不是依赖于类型的名称或标识符。换句话说,如果两个对象具有相同的结构,即它们具有相同的属性和方法,那么它们可以被认为是相同类型或兼容的类型,即使它们的名称不同。在某些语言中也叫做鸭子类型(鸭子辨型)(意思是不以貌取人)

相比之下,名义化类型的兼容性是根据类型的名称或标识符来确定的。在名义化类型系统中,即使两个对象具有相同的结构,如果它们的名称或标识符不同,它们被认为是不同的类型。

结构化类型通常用于动态类型语言,如 JavaScript,而名义化类型通常用于静态类型语言,如 Java 或 C++。

typescript
type Person = {
  name: string;
  age: number;
};

type Animal = {
  name: string;
  age: number;
};

const person: Person = {
  name: "John",
  age: 10,
};

const animal: Animal = person;

function greet(person: Person) {
  console.log(`Hello, ${person.name}`);
}

greet(animal);

Person 类型能够赋值给 Animal 类型,如果是 Java 等后端程序员会觉得这样做不可思议,但是其实将类型去掉,看看编译之后的结果,就能理解了,无非就是简单的对象传值,名字并不是最重要的。

javascript
"use strict";
const person = {
  name: "John",
  age: 10,
};
const animal = person;
function greet(person) {
  console.log(`Hello, ${person.name}`);
}
greet(animal);

同样的,就算是 class 类,一样是结构化类型

javascript
class User {
  constructor(
  	public firstName: string,  // public 是this.firstName=firstName的简写形式
    public lastName: string,
    public age:number) {
  }
}

class Person {
  constructor(public firstName: string, public lastName: string, public age:number) {
  }
}

let a = new Person('lily','smith',20);
let b = new User('john','matt',21);
a = b;