Typescript 学习记录

254 阅读2分钟

接口(Interface)与类型(Type)别名的异同点

相同点

  1. 都可以描述对象或函数
// 接口
interface Sister {
  namestring;
  agenumber;
}

interface SetSister {
  (namestringagenumber): void;
}

// 类型别名
type Sister = {
  namestring;
  agenumber;
};

type SetSister = (name: string, age: number) => void;

  1. 都可以扩展 interface和type可以混合扩展,也就是说interface可以扩展type,type也可以扩展interface。 但需要注意的是,接口的扩展是继承(extends)。类型别名的扩展就是交叉类型(通过&实现)
// 接口\
interface SisterAn {
    namestring;
}

// 类型别名
type SisterRan = {
    agenumber;
}
// 接口扩展接口
interface Sister extends SisterAn {
    agenumber;
}
// 类型别名扩展类型别名\
type SisterPro = SisterRan & {
    name: string;
}
// 类型别名扩展类型别名
type SisterPro = SisterRan & {
    name: string;
}
// 接口扩展类型别名
interface Sister extends SisterRan {
    name: string;
}
// 类型别名扩展接口\
type SisterPro = SisterAn & {
    age: number;
}

不同点

几乎接口的所有特性都可以通过类型别名来实现

  1. 不同的声明范围

与接口不同,可以为任意的类型创建类型别名

类型别名的右边可以是任何类型,包括基本类型、元祖、类型表达式( & 或 | 等);而在接口声明中,右边必须为变量结构。例如,下面的类型别名就不能转换成接口

type Name = string
type Text = string | { text: string };
type Coordinates = [number, number];
  1. 不同的扩展形式 接口是通过继承的方式来扩展,类型别名是通过 & 来扩展
// 接口扩展
interface SisterAn {
    namestring;
}
interface Sister extends SisterAn {
    agenumber;
}

// 类型别名扩展\
type SisterRan = {
    agenumber;
}
type SisterPro = SisterRan & {
    namestring;
}

这里需要注意的是,接口扩展时,typescript 会检查扩展的接口是否可以赋值给被扩展的接口

**// 接口扩展
interface SisterAn {
    namestring;
    agestring;
}

interface Sister extends SisterAn {
    namestring;
    agenumber;
}
// 报错:
//  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 将尽其所能把扩展和被扩展的类型组合在一起,而不会抛出编译时错误

  1. 不同的重复定义表现形式 接口可以定义多次,多次的声明会自动合并
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'.