TypeScript中的Interface和Type:异同及使用场景
Howard 8/19/2021 Typescript
在TypeScript中,有两种用于定义自定义类型的主要方式:interface
(接口)和type
(类型)。它们看起来有些相似,但在某些方面有着不同的用途和特性。在本文中,我们将详细讨论这两者的异同以及它们在什么情况下应该使用。
# Interface(接口)
接口(interface) 主要用于定义对象的结构和形状,以及类与对象之间的契约。接口定义了一组属性和方法,对象或类必须遵循这个接口的契约。
interface User {
name: string;
age: number;
}
interface SetUser {
(name: string, age: number): void;
}
Interface可以拓展(extends)其他接口,这意味着一个接口可以继承另一个接口的成员。
interface Name {
name: string;
}
interface User extends Name {
age: number;
}
Interface可以声明合并。如果多次声明同一个接口,它们会被合并成一个接口。
interface User {
name: string;
age: number;
}
interface User {
sex: string;
}
/*
User 接口最终合并为:
{
name: string;
age: number;
sex: string;
}
*/
Interface可以约束类的构造函数。接口可以用来约束一个类的构造函数,以确保类的实例满足接口定义的要求。
interface Counter {
(start: number): string;
interval: number;
reset(): void;
}
function getCounter(): Counter {
let counter = <Counter>function (start: number) { };
counter.interval = 123;
counter.reset = function () { };
return counter;
}
# Type(类型)
类型(type) 主要用于定义自定义类型,可以表示基本类型别名、联合类型、元组等。
// 基本类型别名
type Name = string;
// 联合类型
type Pet = Dog | Cat;
// 具体定义数组每个位置的类型
type PetList = [Dog, Pet];
Type可以使用typeof获取实例的类型。这在需要获取某个变量的类型时非常有用。
let div = document.createElement('div');
type B = typeof div; // B的类型是HTMLDivElement
Type可以进行其他高级操作,如字符串字面量类型、模板字符串类型、条件类型等,用于创建更复杂的类型。
type StringOrNumber = string | number;
type Text = string | { text: string };
type NameLookup = Dictionary<string, Person>;
type Callback<T> = (data: T) => void;
type Pair<T> = [T, T];
type Coordinates = Pair<number>;
type Tree<T> = T | { left: Tree<T>, right: Tree<T> };
# Interface vs Type
# 共同点
- 都可以描述对象或函数的结构。
- 都可以被继承,或者通过交叉类型(Intersection Types)进行组合。
- 都可以用来声明函数的属性。
# 不同点
Type可以声明基本类型别名、联合类型、元组等,而Interface不行。
// 基本类型别名
type Name = string
// 联合类型
interface Dog {
wong();
}
interface Cat {
miao();
}
type Pet = Dog | Cat
// 具体定义数组每个位置的类型
type PetList = [Dog, Pet]
// 还能通过typeof获取类型
let div = document.createElement('div');
type B = typeof div; // B的类型是HTMLDivElement
Interface可以约束类的构造函数,Type不行。
interface ClockConstructor {
new (hour: number, minute: number): ClockConstructor; // 注意后面的 :ClockConstructor
}
class Clock implements ClockConstructor {
currentTime: Date;
constructor(h: number, m: number) { }
}
Interface可以声明合并,多个相同名字的接口会被合并为一个。
interface User {
name: string
age: number
}
interface User {
sex: string
}
/*
User 接口为 {
name: string
age: number
sex: string
}
*/
# 使用场景
- 当您想要描述对象的形状以及类与对象之间的契约时,使用Interface更为合适。
- 当您需要创建自定义类型别名、联合类型、元组等,使用Type更为适合。
- 如果您不确定该使用哪个,或者只是希望定义一种类型而不是接口,那么应该使用Type。
最后,需要注意的是,TypeScript的发展和版本更新可能会影响这两者的功能和用法,因此建议查看最新的官方文档以获取最新信息。无论您选择使用哪种方式,都可以根据项目的需要来灵活选择,以编写出清晰、健壮且易维护的代码。