1. 什么是接口?
在TypeScript
中,接口是一个非常灵活的概念,除了可用于对类的一部分行为进行抽象以外,也常用语对【对象的形状】进行描述。
2. 接口的使用
interface IPerson{
name: string;
age: number;
gender: boolean
}
定义接口变量,在定义接口变量时,变量的属性比接口声明的少或者多一些属性都是不允许,编译会出错
// 定义变量
let tom: IPerson = {name : 'LelandACM' , age: 30 , height: 180}
//编译会提示错误
- error TS2741: Property 'gender' is missing in type '{ name: string; age: number; }' but required in type 'IPerson'.
- error TS2322: Type '{ name: string; age: number; height: number; }' is not assignable to type 'IPerson'.
Object literal may only specify known properties, and 'height' does not exist in type 'IPerson'.
由此,在变量赋值时,变量的形状必须和接口的形状保持一致,除非在接口中声明部分属性为可选属性。当然可选属性是不允许添加未定义的属性。
interface IPerson {
name: string;
age: number;
gender?: boolean
}
//定义变量添加未定义属性
let tom: IPerson = { name: 'LelandACM', age: 30 , height: 180}
//编译提示错误
- error TS2322: Type '{ name: string; age: number; height: number; }' is not assignable to type 'IPerson'.
Object literal may only specify known properties, and 'height' does not exist in type 'IPerson'.
可以给接口中添加任意属性声明
interface IPerson {
name: string;
age: number;
[propName: string]: any
}
上述示例中,有一个任意属性,需要注意的是如果定义了任意属性,那么确定属性和可选属性必须都是他的类型的子集,否者会编译报错。
interface IPerson {
name: string;
age: number;
gender?: boolean
[propName: string]: string
}
//定义变量
let tom: IPerson = { name: 'LelandACM', age: 30 , height: '180cm'}
//编译报错
interface.ts:3:3 - error TS2411: Property 'age' of type 'number' is not assignable to 'string' index type 'string'.
3 age?: number;~~~
interface.ts:4:3 - error TS2411: Property 'gender' of type 'boolean' is not assignable to 'string' index type 'string'.
4 gender?: boolean ~~~~~~
interface.ts:9:51 - error TS2322: Type 'number' is not assignable to type 'string'.
9 let tom: IPerson = { name: 'LelandACM', age: 30 , height: 180}
interface.ts:5:3
5 [propName: string]: string
一个接口中只能定义一个任意属性,如果接口中有多个类型的属性,则可以在任意属性中使用any类型或者联合类型。
interface IPerson {
name: string;
age: number;
gender?: boolean
[propName: string]: string | number | boolean
}
let tom: IPerson = { name: 'LelandACM', age: 30, height: '180cm' }
也可以在接口中配置只读属性,来对接口部分属性对外不可见
interface IPerson {
readonly id: number
name: string;
age: number;
gender?: boolean
[propName: string]: string | number | boolean
}
let tom: IPerson = { id: 1000 , name: 'LelandACM', age: 30, height: '180cm' }
// 只读属性赋值,编译出错
tom.id = 1001
- error TS2540: Cannot assign to 'id' because it is a read-only property.
注意:只读属性的约束存在第一次给对象赋值时,而不是第一次给只读属性赋值时。
interface IPerson {
readonly id: number
name: string;
age: number;
gender?: boolean
[propName: string]: string | number | boolean
}
//id属性未赋初始值,编译报错
let tom: IPerson = { name: 'LelandACM', age: 30, height: '180cm' }
// 只读属性赋值,编译出错
tom.id = 10001
- error TS2741: Property 'id' is missing in type '{ name: string; age: number; height: string; }' but required in type 'IPerson'.
10 let tom: IPerson = { name: 'LelandACM', age: 30, height: '180cm' }
interface.ts:2:12
2 readonly id: number
'id' is declared here.
interface.ts:12:5 - error TS2540: Cannot assign to 'id' because it is a read-only property.
12 tom.id = 10001
Found 2 errors.
上述示例中,报错信息有两处,一处是对变量tom赋值时,没有给id属性初始值,第二处是在给tom.id赋值时,由于id是只读属性,不可属性赋值,提示出错。