接口(Interface)与类型(Type)别名的异同点
相同点
- 都可以描述对象或函数
// 接口
interface Sister {
name: string;
age: number;
}
interface SetSister {
(name: string, age: number): void;
}
// 类型别名
type Sister = {
name: string;
age: number;
};
type SetSister = (name: string, age: number) => void;
- 都可以扩展
interface和type可以混合扩展,也就是说interface可以扩展type,type也可以扩展interface。 但需要注意的是,接口的扩展是继承(extends)。类型别名的扩展就是交叉类型(通过&实现)
// 接口\
interface SisterAn {
name: string;
}
// 类型别名
type SisterRan = {
age: number;
}
// 接口扩展接口
interface Sister extends SisterAn {
age: number;
}
// 类型别名扩展类型别名\
type SisterPro = SisterRan & {
name: string;
}
// 类型别名扩展类型别名
type SisterPro = SisterRan & {
name: string;
}
// 接口扩展类型别名
interface Sister extends SisterRan {
name: string;
}
// 类型别名扩展接口\
type SisterPro = SisterAn & {
age: number;
}
不同点
几乎接口的所有特性都可以通过类型别名来实现
- 不同的声明范围
与接口不同,可以为任意的类型创建类型别名
类型别名的右边可以是任何类型,包括基本类型、元祖、类型表达式( & 或 | 等);而在接口声明中,右边必须为变量结构。例如,下面的类型别名就不能转换成接口
type Name = string
type Text = string | { text: string };
type Coordinates = [number, number];
- 不同的扩展形式
接口是通过继承的方式来扩展,类型别名是通过
&来扩展
// 接口扩展
interface SisterAn {
name: string;
}
interface Sister extends SisterAn {
age: number;
}
// 类型别名扩展\
type SisterRan = {
age: number;
}
type SisterPro = SisterRan & {
name: string;
}
这里需要注意的是,接口扩展时,typescript 会检查扩展的接口是否可以赋值给被扩展的接口
**// 接口扩展
interface SisterAn {
name: string;
age: string;
}
interface Sister extends SisterAn {
name: string;
age: number;
}
// 报错:
// Interface 'Sister' incorrectly extends interface 'SisterAn'.
// Types of property 'age' are incompatible.
// Type 'number' is not assignable to type 'string'**
但使用交集类型时就不会出现这种情况
// 类型别名扩展
type SisterRan = {
name: string;
age: string;
}
type SisterPro = SisterRan & {
name: string;
age: number;
}
类型别名扩展时,typescript 将尽其所能把扩展和被扩展的类型组合在一起,而不会抛出编译时错误
- 不同的重复定义表现形式 接口可以定义多次,多次的声明会自动合并
interface Sister {
name: string;
}
interface Sister {
age: number;
}
const sisterAn: Sister = {
name: 'sisterAn'
}
// 报错:Property 'age' is missing in type '{ name: string; }' but required in type 'Sister'
const sisterRan: Sister = {
name: 'sisterRan',
age: 12;
}
// 正确
但是类型别名如果定义多次,会报错
type Sister = { // Duplicate identifier 'Sister'
name: string;
}
type Sister = { // Duplicate identifier 'Sister'
age: number;
}
虽然官方中说几乎接口的所有特性都可以通过类型别名来实现,但建议优先选择接口,接口满足不了再使用类型别
// 接口扩展
interface Sister {
sex: number;
}
interface SisterAn extends Sister {
sex: string;
}
// index.ts(5,11): error TS2430: Interface 'SisterAn' incorrectly extends interface 'Sister'.
// Types of property 'sex' are incompatible.
// Type 'string' is not assignable to type 'number'.