Skip to content

前言

在 TypeScript 中,我们使用接口(Interfaces)来定义对象的类型。

什么是接口

在面向对象语言中,接口(Interfaces)是一个很重要的概念,它是对行为的抽象,而具体如何行动需要由类(classes)去实现(implement)。

TypeScript 中的接口是一个非常灵活的概念,除了可用于对类的一部分行为进行抽象以外,也常用于对「对象的形状(Shape)」进行描述。

简单案例

js
interface Preson {
    name: string,
    age: number,
    sex: string
}

let obj: Preson = {
    name: 'Jack Yang',
    age: 18,
    sex: '男'
}

分析
		1.定义接口Preson,定义三个参数,并定义对应的类型
		2.定义对象obj,指定接口类型Preson,那么obj的参数和类型就必须按照接口定义的一致去写

多一些属性和少一些属性都是不允许的,可以看到,在定义的时候,如果和接口的形状不一致,编译器就会给我们提示。

可选属性

有时候我们希望不和接口定义的形状完全一致,那么我们可以在接口定义是使用可选属性

js
interface Preson {
    name: string,
    age: number,
    sex?: string
}

let obj: Preson = {
    name: 'Jack Yang',
    age: 18
}
或者
let obj: Preson = {
    name: 'Jack Yang',
    age: 18,
    sex: '男'
}

分析
	此时name和age属性是必须的,sex属性变为可选
  此时也不允许添加未定义的属性

任意属性

有时候我们需要接口有任意的属性,那么我们可以这样去定义.

js
interface Preson {
    name: string,
    age: number,
    sex?: string,
    [propName:string]: any
}

let obj: Preson = {
    name: 'Jack Yang',
    age: 18,
    sex: '男',
    length: 180
}

分析
	[propName:string]:定义了任意属性取string类型的值。即length为string值,180取任意值
  any:定义任意属性取任意类型值

注意
	propName:取之为string或者number

一旦定义的任意属性,那么可选属性和必选属性都必须是它类型的子类型。注意,一个接口中只能定义一个任意类型。

js
interface Preson {
    name: string,
    age: number,
    sex?: string,
    [propName:string]: string
}

let obj: Preson = {
    name: 'Jack Yang',
    age: 18,
    sex: '男',
    length: '1'
}

Type '{ name: string; age: number; sex: string; length: string; }' is not assignable to type 'Preson'.
  Property 'age' is incompatible with index signature.
    Type 'number' is not assignable to type 'string'.

分析
	任意属性值的类型是string,此时name和sex是string,age是number,number并不是string的子类型,所以这里会报错

解决
	此时可以使用联合类型定义

interface Preson {
    name: string,
    age: number,
    sex?: string,
    [propName:string]: number | string
}

let obj: Preson = {
    name: 'Jack Yang',
    age: 18,
    sex: '男',
    a: 2
}

只读属性

如果我们希望一个属性只在被创建的时候被定义,不允许被修改,那么我们可以使用只读属性,reldonly。类型与js中的const定义变量,一旦被定义了就不允许修改。

js
interface Preson {
    name: string,
    readonly age: number,
    sex?: string,
    [propName:string]: number | string
}

let obj: Preson = {
    name: 'Jack Yang',
    age: 18,
    sex: '男',
    a: 2
}

obj.age = 19;	//Cannot assign to 'age' because it is a read-only property.

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

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

let tom: Person = {
    name: 'Tom',
    gender: 'male'
};

tom.id = 89757;

// index.ts(8,5): error TS2322: Type '{ name: string; gender: string; }' is not assignable to type 'Person'.
//   Property 'id' is missing in type '{ name: string; gender: string; }'.
// index.ts(13,5): error TS2540: Cannot assign to 'id' because it is a constant or a read-only property.

分析
	第一次报错:是在对tom赋值的时候,没有给id进行赋值
  第二处报错:是在tom.id赋值的时候,因为不允许给只读属性赋值

总结

  1. 接口的定义属性有必选,可选,任意,只读,任意值类型只能是一个,其它的可以是任意个。
  2. 定义类型时并不是唯一,可以使用联合类型。
  3. 对象的定义要和接口定义的一致,不可以出现未定义的类型值,任意值除外