使用 interface 定义接口 对象类型接口和函数类型接口 接口可以约束对象,函数,类的结构和类型,是一种代码协作必须遵守的契约

接口事列

  1. interface List {
  2. id: number;
  3. name: string;
  4. }
  5. interface Result {
  6. data: List[];
  7. }
  8. function render(result: Result) {
  9. result.data.forEach((value) => {
  10. console.log(value.id, value.name);
  11. });
  12. }
  13. let result = {
  14. data: [
  15. { id: 1, name: "JS" },
  16. { id: 2, name: "TS" }
  17. ],
  18. };
  19. render(result);

image.png

额外属性

在接口的实际调用中,后端也经常会传递约定之外的字段,如

  1. interface List {
  2. id: number;
  3. name: string;
  4. }
  5. interface Result {
  6. data: List[];
  7. }
  8. function render(result: Result) {
  9. result.data.forEach((value) => {
  10. console.log(value.id, value.name);
  11. });
  12. }
  13. let result = {
  14. data: [
  15. { id: 1, name: "JS", remark:"" }, // 接口约定以外的remark字段
  16. { id: 2, name: "TS" }
  17. ],
  18. };
  19. render(result);

传入接口以外的字段remark是并没有报错,ts允许这种情况的发生

只要传入的对象满足接口的必要条件就可以被允许,即使传入多余的字段也可以通过类型检查

但也有例外,如果直接传入对象字面量,TS就会对额外的字段进行类型检查,如下:

  1. render({
  2. data: [
  3. { id: 1, name: "JS", remark:"" }, // 接口约定以外的remark字段
  4. { id: 2, name: "TS" }
  5. ],
  6. });

image.png

绕过检查的方法有3种

  1. 将对象字面量赋值给一个变量 ```typescript let result = { data: [
    1. { id: 1, name: "JS", remark:"" }, // 接口约定以外的remark字段
    2. { id: 2, name: "TS" }
    ], }; render(result);
  1. 2. 使用类型断言
  2. ```typescript
  3. // one
  4. render({
  5. data: [
  6. { id: 1, name: "JS", remark: "" }, // 接口约定以外的remark字段
  7. { id: 2, name: "TS" },
  8. ],
  9. } as Result);
  10. // two
  11. render(<Result>{
  12. data: [
  13. { id: 1, name: "JS", remark: "" }, // 接口约定以外的remark字段
  14. { id: 2, name: "TS" },
  15. ],
  16. });
  1. 使用字符串索引签名

    表示用任意字符串去索引List,可得到任意结果,此时List可以实现支持多个属性

  1. interface List {
  2. id: number;
  3. name: string;
  4. [remark: string]: any;
  5. }

接口成员

可选属性

对于一个约定好的接口类型,其中有些字段并不是一定会存在的,是可选属性 而之前在接口中声明的字段,是必须要满足的字段,不可以缺少

声明方式:
接口属性? 类型注解

  1. interface List {
  2. id: number;
  3. name: string;
  4. // [x: string]: any;
  5. age?: number;
  6. }
  7. interface Result {
  8. data: List[];
  9. }
  10. function render(result: Result) {
  11. result.data.forEach((value) => {
  12. console.log(value.id, value.name); // 1 "JS" 2 "TS"
  13. if (value.age) {
  14. console.log(value.age); // 10
  15. }
  16. });
  17. }
  18. let result = {
  19. data: [
  20. { id: 1, name: "JS", remark: "" }, // 接口约定以外的remark字段
  21. { id: 2, name: "TS", age:10 },
  22. ],
  23. };
  24. render(result);

只读属性

有时候我们希望对象中的一些字段只能在创建的时候被赋值,那么可以用 readonly 定义只读属性

  1. interface List {
  2. readonly id: number; // 只读属性
  3. name: string;
  4. // [x: string]: any;
  5. age?: number;
  6. }
  7. interface Result {
  8. data: List[];
  9. }
  10. function render(result: Result) {
  11. result.data.forEach((value) => {
  12. console.log(value.id, value.name); // 1 JS" 2 "TS"
  13. if (value.age) {
  14. console.log(value.age); // 10
  15. }
  16. value.id++; // 修改只读属性
  17. });
  18. }
  19. let result = {
  20. data: [
  21. { id: 1, name: "JS", remark: "" },
  22. { id: 2, name: "TS", age:10 },
  23. ],
  24. };
  25. render(result);

image.png

可索引类型的接口

数字索引接口

声明一个数字索引类型的接口 表示用任意数字去索引 number Index都会得到一个 string

  1. interface StringArray {
  2. [index: number]: string;
  3. }
  4. // 相当于声明了一个字符串类型的数组
  5. let chars: StringArray = ["A", "B"];

字符串索引接口

声明一个字符串索引类型的接口 表示用任意的字符串去索引 string Index 得到的结果都是 string

  1. interface stringIndex {
  2. [x: string]: string;
  3. }
  4. // 这样声明后,就不能声明 number 类型的成员了,会报错
  5. interface stringIndex {
  6. [x: string]: string;
  7. y: number; // Property 'y' of type 'number' is not assignable to string index type 'string'.
  8. }

两种索引签名混用

注: 数字索引的返回值,一定要是字符串返回类型的子类型 这是因为JS会进行类型转换,将number转换成string,这样就能保证类型的兼容性

  1. // 在上边的字符串索引接口stringIndex中,添加数字索引签名
  2. interface stringIndex {
  3. [x: string]: string;
  4. [z: number]: string;
  5. }
  6. // 如:将数组索引的返回值改成number
  7. // interface Names {
  8. // [x: string]: string;
  9. // // y: number;
  10. // [z: number]: number;
  11. // }
  12. interface Names {
  13. [x: string]: any;
  14. // y: number;
  15. [z: number]: number;
  16. }

image.png

学习笔记出自于梁宵老师课程