【TypeScript】TS中type和interface在类型声明时的区别

举报
猫先生c 发表于 2023/09/28 09:12:25 2023/09/28
【摘要】 一、专栏介绍vue3+vite+typeScript从入门到实践是博主在学习和工作过程中的总结,实用性非常强,内容会不断进行精进,欢迎订阅哦,学会TS不迷路。TS系列标题基础篇TS入门(一)基础篇TS类型声明(二)基础篇TS接口类型(三)基础篇TS交叉类型&联合类型(四)基础篇TS类型断言(五)基础篇TS类型守卫(六)==进阶篇==TS函数重载(七)==进阶篇==TS泛型(八)==进阶篇=...

在这里插入图片描述

一、专栏介绍

vue3+vite+typeScript从入门到实践是博主在学习和工作过程中的总结,实用性非常强,内容会不断进行精进,欢迎订阅哦,学会TS不迷路。

TS系列 标题
基础篇 TS入门(一)
基础篇 TS类型声明(二)
基础篇 TS接口类型(三)
基础篇 TS交叉类型&联合类型(四)
基础篇 TS类型断言(五)
基础篇 TS类型守卫(六)
==进阶篇== TS函数重载(七)
==进阶篇== TS泛型(八)
==进阶篇== TS装饰器(九)
==进阶篇== TS条件类型(十)
==进阶篇== TS自定义类型之对象属性必选、对象属性可选
==进阶篇== TS中type和interface在类型声明时的区别

二、TS中type和interface在类型声明时的区别

在TS中interfacetype都可以用来自定义数据类型,两者有许多相同之处,但是也有差别。我们一般选择 type 来定义基本类型别名、联合类型、元组等类型,而选择 interface 来定义复杂的对象、类、以及进行接口的继承。

1. 声明常见类型

(1)定义基本类型

type Age = number;

interface Person {
  name: string;
  age: Age;
}

(2)定义函数类型

type Greeting = (name: string) => string;

interface Greeter {
  (name: string): string;
}

(3)定义对象类型

type Point = { x: number; y: number };

interface Rectangle {
  width: number;
  height: number;
  position: Point;
}

(4)定义泛型

type List<T> = {
  data: T[];
  add: (item: T) => void;
}

interface List<T> {
  data: T[];
  add: (item: T) => void;
}

interface使用泛型的案例如下:

interface Container<T> {
  value: T;
  get(): T;
  set(value: T): void;
}

class NumberContainer implements Container<number> {
  value: number;
  get() {
    return this.value;
  }
  set(value: number) {
    this.value = value;
  }
}

const container = new NumberContainer();
container.set(42);
console.log(container.get()); // 

2. interface 可以被类(class)实现(implement),而 type 不能

interface Animal {
  name: string;
  speak: () => void;
}

class Dog implements Animal {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  speak() {
    console.log("hello!");
  }
}
const myDog = new Dog("Sparky");
myDog.speak(); // 输出 hello

上面代码使用interface 定义了 namespeak 方法的 Animal 接口,然后使用 class 实现了该接口,并创建了一个 Dog 的实例,调用了speak方法。

type Animal = {
  name: string;
  speak: () => void;
}

class Dog implements Animal {
  // 这里会报错,因为 Animal 是一个类型别名,不能被 class 实现
}

上述代码会在编译时报错,==因为 type 定义的 Animal 类型只是一个别名,并不是一个接口,不能被类实现。所以在需要定义一个可以被类实现的类型时,应该使用 interface 进行定义。==

3. interface 支持 extends 实现接口的继承,而 type 不支持

(1)单接口继承

interface Animal {
	name: string;
	speak: () => void;
  }
  
interface Pet extends Animal {
	owner: string;
	play: () => void;
  }
  
class Dog implements Pet {
	name: string;
	owner: string;
	constructor(name: string, owner: string) {
	  this.name = name;
	  this.owner = owner;
	}
	speak() {
	  console.log("speak:hello");
	}
	play() {
	  console.log(`${this.name} is playing with ${this.owner}`);
	}
  }
  
  const myDog = new Dog("myPet", "Mr.Cat");
  myDog.speak(); // 输出 "speak:hello" 
  myDog.play(); // 输出 "myPet is playing with Mr.Cat" 

(2)多接口继承

==由于 type 只是类型别名,不能包含具体的属性和方法实现,因此它不支持通过 extends 关键字实现接口的继承。如果需要继承类型别名,需要使用交叉类型进行组合。==

==当你需要让一个接口继承多个其他接口时,使用 interface 更加方便。因为 interface 允许你使用逗号分隔的方式来继承多个接口,而 type 只能使用交叉类型(&)来实现继承。==

例如:

interface Person {
  name: string;
  age: number;
}

interface Employee {
  company: string;
  jobTitle: string;
}

interface Manager extends Person, Employee {
  teamSize: number;
}

const manager: Manager = {
  name: 'John Doe',
  age: 40,
  company: 'ABC Inc.',
  jobTitle: 'Manager',
  teamSize: 10,
};

在上面的例子中,我们定义了三个接口:PersonEmployeeManagerManager 接口继承了 PersonEmployee 接口,以及自己的属性 teamSize。如果使用 type 来定义 Manager类型,那么就需要使用交叉类型来实现继承,但是这么实现起来就比较复杂。

总的来说,interface 和 type 都有自己的优势和使用场景。在 TypeScript 3.7 版本之后,type 也可以实现声明合并和继承多个类型的功能,因此在选择使用 interface 还是 type 时,应该根据具体情况来决定。

4.interface 可以定义多个同名接口并合并,而 type 不支持

==当合并两个或多个具有相同名称的接口或类型时, interface 允许声明多个同名接口并将它们合并成一个。== 例如:

interface User {
  name: string;
  age: number;
}

interface User {
  gender: 'male' | 'female';
}

const user: User = {
  name: '猫先生',
  age: 25,
  gender: 'male',
};

在上面的例子中,我们声明了两个同名的接口 User,并将它们合并成一个。如果使用 type 来定义 User 类型,那么就无法实现声明合并的功能,代码会直接报错。

5.type可以使用 typeof 获取实例的类型,而 interface 不支持

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

const john: Person = {
  name: "John",
  age: 30,
}

type PersonType = typeof john; // 类型为 { name: string, age: number }

在这里插入图片描述

在上图可以看到PersonType类型和Person类型一样,通过typeof获取john的数据类型,然后赋值给PersonType类型。

==interface 不支持使用typeof操作符获取实例的类型。因为interface只是一种接口定义,它本身不是一个值,无法获取其类型。==

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。