1. 什么是接口?

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

2. 接口的使用

  1. interface IPerson{
  2. name: string;
  3. age: number;
  4. gender: boolean
  5. }

定义接口变量,在定义接口变量时,变量的属性比接口声明的少或者多一些属性都是不允许,编译会出错

  1. // 定义变量
  2. let tom: IPerson = {name : 'LelandACM' , age: 30 , height: 180}
  3. //编译会提示错误
  4. - error TS2741: Property 'gender' is missing in type '{ name: string; age: number; }' but required in type 'IPerson'.
  5. - error TS2322: Type '{ name: string; age: number; height: number; }' is not assignable to type 'IPerson'.
  6. Object literal may only specify known properties, and 'height' does not exist in type 'IPerson'.

由此,在变量赋值时,变量的形状必须和接口的形状保持一致,除非在接口中声明部分属性为可选属性。当然可选属性是不允许添加未定义的属性。

  1. interface IPerson {
  2. name: string;
  3. age: number;
  4. gender?: boolean
  5. }
  6. //定义变量添加未定义属性
  7. let tom: IPerson = { name: 'LelandACM', age: 30 , height: 180}
  8. //编译提示错误
  9. - error TS2322: Type '{ name: string; age: number; height: number; }' is not assignable to type 'IPerson'.
  10. Object literal may only specify known properties, and 'height' does not exist in type 'IPerson'.

可以给接口中添加任意属性声明

  1. interface IPerson {
  2. name: string;
  3. age: number;
  4. [propName: string]: any
  5. }

上述示例中,有个任意属性,需要注意的是如果定义了任意属性,那么确定属性和可选属性必须都是他的类型的子集,否者会编译报错。

  1. interface IPerson {
  2. name: string;
  3. age: number;
  4. gender?: boolean
  5. [propName: string]: string
  6. }
  7. //定义变量
  8. let tom: IPerson = { name: 'LelandACM', age: 30 , height: '180cm'}
  9. //编译报错
  10. interface.ts:3:3 - error TS2411: Property 'age' of type 'number' is not assignable to 'string' index type 'string'.
  11. 3 age?: number;~~~
  12. interface.ts:4:3 - error TS2411: Property 'gender' of type 'boolean' is not assignable to 'string' index type 'string'.
  13. 4 gender?: boolean ~~~~~~
  14. interface.ts:9:51 - error TS2322: Type 'number' is not assignable to type 'string'.
  15. 9 let tom: IPerson = { name: 'LelandACM', age: 30 , height: 180}
  16. interface.ts:5:3
  17. 5 [propName: string]: string

一个接口中只能定义一个任意属性,如果接口中有多个类型的属性,则可以在任意属性中使用any类型或者联合类型。

  1. interface IPerson {
  2. name: string;
  3. age: number;
  4. gender?: boolean
  5. [propName: string]: string | number | boolean
  6. }
  7. let tom: IPerson = { name: 'LelandACM', age: 30, height: '180cm' }

也可以在接口中配置只读属性,来对接口部分属性对外不可见

  1. interface IPerson {
  2. readonly id: number
  3. name: string;
  4. age: number;
  5. gender?: boolean
  6. [propName: string]: string | number | boolean
  7. }
  8. let tom: IPerson = { id: 1000 , name: 'LelandACM', age: 30, height: '180cm' }
  9. // 只读属性赋值,编译出错
  10. tom.id = 1001
  11. - error TS2540: Cannot assign to 'id' because it is a read-only property.

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

  1. interface IPerson {
  2. readonly id: number
  3. name: string;
  4. age: number;
  5. gender?: boolean
  6. [propName: string]: string | number | boolean
  7. }
  8. //id属性未赋初始值,编译报错
  9. let tom: IPerson = { name: 'LelandACM', age: 30, height: '180cm' }
  10. // 只读属性赋值,编译出错
  11. tom.id = 10001
  12. - error TS2741: Property 'id' is missing in type '{ name: string; age: number; height: string; }' but required in type 'IPerson'.
  13. 10 let tom: IPerson = { name: 'LelandACM', age: 30, height: '180cm' }
  14. interface.ts:2:12
  15. 2 readonly id: number
  16. 'id' is declared here.
  17. interface.ts:12:5 - error TS2540: Cannot assign to 'id' because it is a read-only property.
  18. 12 tom.id = 10001
  19. Found 2 errors.

上述示例中,报错信息有两处,一处是对变量tom赋值时,没有给id属性初始值,第二处是在给tom.id赋值时,由于id是只读属性,不可属性赋值,提示出错。