【青训营】-TypeScript入门之进阶篇

496 阅读4分钟

本篇先从类型操作(keyof)说起,然后主要说的是TypeScript进阶的接口和类。提示:图片代码里的注释可以认真看一下哟!

前言

『前期回顾』

TypeScript入门之预备知识

TypeScript入门之基础知识

image-20210822225504302

类型操作(keyof)

keyof (引类型查询操作符)

  • 是在TS2.1引入的。

  • 它获取类型上所有已知、public的键对应的类型联合

  • number,string,symbol(TS4.4之后开始支持)三种类型可以作为key

  • number[]等同于Array<number>(这个要记住)

image-20210822234402126

简单类型的keyof

  type K1 = keyof unknown; // never
  type K3 = keyof undefined; // never
  type K4 = keyof void; // never
  type K5 = keyof null; // never
  type K11 = keyof object;  // never
  type K12 = keyof never;  // never

  type K2 = keyof any;  // string | number | symbol

key来自对应的interface : Number, BigInt, Boolean, String, Symbol

image-20210822234735465

接口( Interface )

什么是接口?

接口(Interfaces)是对行为的抽象,具体如何行动需要由类(classes)去实现(implement)。除了可用于对类的一部分行为进行抽象以外,也常用于对「对象的形状(Shape)」进行描述。

示例1

  • 定义一个接口IPerson
  • 定义一个变量customer,它的类型是IPerson
  • customer实现接口 IPerson 的属性和方法

(左边TS,右边编译后的JS)

image-20210823233413040

示例2

  • 现在我们再定义一个变量visitor

  • 这次变量少了一个属性lastName

  • 可以看到TS给我们提示了错误

    【说明定义的变量比接口的属性少是不允许的

image-20210823233815941

示例3

  • 又定义了一个变量traveler

  • 这次变量多加了一个属性name

  • 可以看到TS也给我们提示了错误

    【说明定义的变量比接口的属性多也是不允许的

image-20210823234204044

知识点

  • 接口一般首字母大写。有的编程语言中会建议接口的名称加上 I 前缀
  • 接口起到一种限制和规范的作用
  • 赋值的时候,变量的形状必须和接口的形状保持一致

可选属性

上面的示例中,我们看到,定义的变量是不能比接口的属性少的,如果想少怎么办?

可以用【可选属性】,就是在属性名后面加一个?

image-20210823234647719

任意属性

我们现在实现了属性可以比接口少,但是如果【定义的变量想比接口的属性多】怎么办?

我们可以使用【任意属性】来实现,任意属性有两种定义的方式(指的是属性名)

  • 一种属性(索引)签名是 string 类型
  • 一种属性(索引)签名是 number 类型
[propNum: string]: string

image-20210824001353775

image-20210824002155864

[propNum: number]: string

image-20210824002447585

  • 一旦定义了任意属性,那么其他属性(确定属性、可选属性、只读属性等)的类型都必须是它的类型的子集

理解示例

image-20210824003349652

image-20210824004203214

可以改成这样(联合类型)

[propNum: string]: string | number;

image-20210824002958863

有一个特殊的情况number 类型的任意属性签名不会影响其他 string 类型的属性签名

image-20210824004613752

  • 两种任意类型签名并存时,【number 类型的签名】指定的值类型必须是 【string 类型的签名】指定的值类型的子集

理解示例

因为 Functionobject 的子集,所以定义不报错

image-20210824003631545

number 类型的签名】指定的值类型必须是 【string 类型的签名】指定的值类型的子集。

这是因为当使用 number来索引时,JavaScript会将它转换成string然后再去索引对象。 也就是说用 100(一个number)去索引等同于使用"100"(一个string)去索引

接口和类型别名

接口( Interface )与类型别名(Type aliases)可以认为是同一概念的两种语法

类比:

函数定义与函数表达式

对比:

定义相同类型时,接口与类型别名的写法

image-20210822234948857

区别

接口( Interface )与类型别名(Type aliases)的区别?

  • 类型别名更为通用,其右侧可以包含类型表达式(类型联合、类型交叉、条件类型),但接口右侧只能是某种结构( {...} )
  • 接口间继承( extends )时TS会检查二者关系。但类型联合时TS会尽最大努力尝试, 不会报错
  • 同一个作用域中的多个同名接口声明会被合并。而多个同名类型别名会报错

类(class)

class是ES2015引|入的新特性,这里只讲如何用interface描述一个class?

class本质上还是一个函数

  • 作为构造器的函数,必须具有prototype属性。 并且prototype类型和构造器返回值的类型相同
  • 和Point constructor具有相同的函数签名和返回值

image-20210822235626247

定义构造器的语法: new(x: X, y: Y, ...): ReturnType

重要

需要明确,在描述一个class时,我们不是在描述一个对象,而是一个函数,这个函数上有一个prototype属性

结语

字节青训营

本节课的讲师:字节前端—王韦华

如以上有错误的地方,请在评论区中指出!


如果有收获的话,就留个鼓励一下吧!😘