前言

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

什么是接口

在面向对象语言中,接口(Interfaces)是一个很重要的概念,它是对行为的抽象,而具体如何行动需要由类(classes)去实现(implement)。
TypeScript 中的接口是一个非常灵活的概念,除了可用于对类的一部分行为进行抽象以外,也常用于对「对象的形状(Shape)」进行描述。

简单案例

  1. interface Preson {
  2. name: string,
  3. age: number,
  4. sex: string
  5. }
  6. let obj: Preson = {
  7. name: 'Jack Yang',
  8. age: 18,
  9. sex: '男'
  10. }
  11. 分析
  12. 1.定义接口Preson,定义三个参数,并定义对应的类型
  13. 2.定义对象obj,指定接口类型Preson,那么obj的参数和类型就必须按照接口定义的一致去写

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

可选属性

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

  1. interface Preson {
  2. name: string,
  3. age: number,
  4. sex?: string
  5. }
  6. let obj: Preson = {
  7. name: 'Jack Yang',
  8. age: 18
  9. }
  10. 或者
  11. let obj: Preson = {
  12. name: 'Jack Yang',
  13. age: 18,
  14. sex: '男'
  15. }
  16. 分析
  17. 此时nameage属性是必须的,sex属性变为可选
  18. 此时也不允许添加未定义的属性

任意属性

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

  1. interface Preson {
  2. name: string,
  3. age: number,
  4. sex?: string,
  5. [propName:string]: any
  6. }
  7. let obj: Preson = {
  8. name: 'Jack Yang',
  9. age: 18,
  10. sex: '男',
  11. length: 180
  12. }
  13. 分析
  14. [propName:string]:定义了任意属性取string类型的值。即lengthstring值,180取任意值
  15. any:定义任意属性取任意类型值
  16. 注意
  17. propName:取之为string或者number

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

  1. interface Preson {
  2. name: string,
  3. age: number,
  4. sex?: string,
  5. [propName:string]: string
  6. }
  7. let obj: Preson = {
  8. name: 'Jack Yang',
  9. age: 18,
  10. sex: '男',
  11. length: '1'
  12. }
  13. Type '{ name: string; age: number; sex: string; length: string; }' is not assignable to type 'Preson'.
  14. Property 'age' is incompatible with index signature.
  15. Type 'number' is not assignable to type 'string'.
  16. 分析
  17. 任意属性值的类型是string,此时namesexstringagenumbernumber并不是string的子类型,所以这里会报错
  18. 解决
  19. 此时可以使用联合类型定义
  20. interface Preson {
  21. name: string,
  22. age: number,
  23. sex?: string,
  24. [propName:string]: number | string
  25. }
  26. let obj: Preson = {
  27. name: 'Jack Yang',
  28. age: 18,
  29. sex: '男',
  30. a: 2
  31. }

只读属性

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

  1. interface Preson {
  2. name: string,
  3. readonly age: number,
  4. sex?: string,
  5. [propName:string]: number | string
  6. }
  7. let obj: Preson = {
  8. name: 'Jack Yang',
  9. age: 18,
  10. sex: '男',
  11. a: 2
  12. }
  13. obj.age = 19; //Cannot assign to 'age' because it is a read-only property.

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

  1. interface Person {
  2. readonly id: number;
  3. name: string;
  4. age?: number;
  5. [propName: string]: any;
  6. }
  7. let tom: Person = {
  8. name: 'Tom',
  9. gender: 'male'
  10. };
  11. tom.id = 89757;
  12. // index.ts(8,5): error TS2322: Type '{ name: string; gender: string; }' is not assignable to type 'Person'.
  13. // Property 'id' is missing in type '{ name: string; gender: string; }'.
  14. // index.ts(13,5): error TS2540: Cannot assign to 'id' because it is a constant or a read-only property.
  15. 分析
  16. 第一次报错:是在对tom赋值的时候,没有给id进行赋值
  17. 第二处报错:是在tom.id赋值的时候,因为不允许给只读属性赋值

总结

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