TypeScript 中 interface 与 type 的区别

Interface (接口)

在 TypeScript 中,使用 interface (接口)来定义对象的类型,在面向对象语言中,接口是对行为的抽象,而具体如何行动,则需要 class 或者 implement 去实现,在 TypeScript 中,接口可以对 类的一部分行为 进行抽象,也常常用于对 对象的形状(Shape)进行描述

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

const me: Person = {
  name: 'Pan Tao',
  age: 30
}

在上面的示例中,先定义了一个名为 Person 的接口,接着定义了一个常量 me,它的类型是 Person,这样就约束了 me 的形状必须与接口 Person 一致,接口一般首字母大写。

注意:有一些编程语言建议接口的名称前面加上 I 作为前缀,表示这是一个 Interface

当定义了一个变量的接口类型之后,他的属性就不能比定义的多也不能比定义的少,赋值的时候,变量的形状必须和接口的形状保持一致

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

let me: Person = {
    name: 'Pan Tao'
};

上面会报错:

index.ts(6,5): error TS2322: Type '{ name: string; }' is not assignable to type 'Person'.
  Property 'age' is missing in type '{ name: string; }'.
interface Person {
    name: string;
    age: number;
}

let me: Person = {
    name: 'Pan Tao',
    age: 30,
    gender: 'male'
};

上面会报错:

// index.ts(9,5): error TS2322: Type '{ name: string; age: number; gender: string; }' is not assignable to type 'Person'.
//   Object literal may only specify known properties, and 'gender' does not exist in type 'Person'.

可选属性与任意属性以及只读属性

有时候我们希望不要完全匹配,那么就可以使用可选属性或者任意属性

可选属性

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

const me: Person = {
  name: 'Pan Tao'
}

在定义一个属性是,如果属性名后面加一个 ? 号,则表示该属性是可选的,在定义对象时,可以提供也可以不提供

任意属性

interface Person {
  name: string;
  age?: number;
  [propName: string]: any;
}


const me: Person = {
    name: 'Pan Tao',
    age: 30,
    gender: 'male'
};

const you: Person = {
  name: 'Name'
}

[propName: string]: any; 定义了属性名为 string 类型,值可为任意类型的属性。

如果我们给任意属性的值定义了类型,那么所有确定属性和可选属性的值类型也必须是任意属性值类型的子集

interface Person {
    name: string;
    age?: number;
    [propName: string]: string;
}

const me: Person = {
    name: 'Pan Tao',
    age: 30,
    gender: 'male'
};

上面的代码会报错:

// index.ts(3,5): error TS2411: Property 'age' of type 'number' is not assignable to string index type 'string'.
// index.ts(7,5): error TS2322: Type '{ [x: string]: string | number; name: string; age: number; gender: string; }' is not assignable to type 'Person'.
//   Index signatures are incompatible.
//     Type 'string | number' is not assignable to type 'string'.
//       Type 'number' is not assignable to type 'string'.

只读属性

interface Person {
    readonly id: number;
    name: string;
    age?: number;
    [propName: string]: any;
}

const me: Person = {
    id: 1,
    name: 'Pan Tao',
    gender: 'male'
};

tom.id = 2;

id 是只读属性,只能在创建的时候被赋值,之后不再允许被修改:

// index.ts(14,5): error TS2540: Cannot assign to 'id' because it is a constant or a read-only property.

注意,只读的约束存在于第一次给对象赋值的时候,而不是第一次给只读属性赋值的时候。

描述一个函数

interface 可以像下面这样描述一个函数:

interface Person {
    readonly id: number;
    name: string;
    age?: number;
    [propName: string]: any;
}

interface CreatePerson {
  (name: string, age: number) => Person;
}

extends

interface Person {
  readonly id: number;
  name: string;
  age?: number;
  [propName: string]: any;
}

interface Programmer extends Person {
  skills: Array<string>;
}

Type (类型)

区别

标签: TypeScript, Interface, Type

评论已关闭