typescript学习-类型操作(一)

80 阅读3分钟

以下总结可能会基于泛型操作,需提前了解泛型

一、keyof类型操作

keyof作用于一个A类型,并生成一个新的B类型,这个B类型的取值是A类型中所有属性名称所构成的联合类型

  • 正常示例:

    type TypeA = {
      a:string,
      b:number,
      c:boolean
    }
    type TypeB = TypeA // 'a' | 'b' | 'c'
    
  • 索引类型(string):

    type TypeA = {
      [index:string]:string
    }
    type TypeB = keyof TypeA // string | number
    

    当作用类型是索引类型,且属性名类型是string时,新类型是string | number的联合类型。因为即使是number类型的属性名,最终也会转换成string类型。参考以下:

    type TypeA = {
      [index:string]:string
    }
    let a:TypeA = {
      name:'name',
      1:'数字'
    }
    
  • 索引类型(number):

    type TypeA = {
      [index:number]:string
    }
    type TypeB = keyof TypeA  // number
    

    当属性名类型是number时,则新类型只能是number

二、typeof类型操作

在jvascript中,typeof操作符用于确定一个基础类型。但在typescript中,针对这个操作符做出了一些增强,可以返回变量或属性的类型。这个操作符针对基础类型,并没有太多的作用,但结合其他的类型操作符,可以方便的表达很多类型。

  • 示例:

    function f() {
      return { x: 10, y: 3 };
    }
    type P = ReturnType<typeof f>;
    // 通过typeof获取一个方法的类型,在推断获取其返回类型
    // type P = {
    //   x: number;
    //   y: number;
    // }
    type Union = P & {
      z:number
    }
    // type P = {
    //   x: number;
    //   y: number;
    //   z: number
    // }
    

    值得注意的是,在javascript中,使用typeof操作符用于一个方法或者对象,只会返回基础类型object或者function,但在typescript中,会去获取其具体类型定义。

  • 限制

    在typescript中,typeof的操作特意的被限制了部分行为。理论上来将,typeof可以用于任意合法的表达式,以下2个操作在理论上相等:

    function msgbox(){
      return {
        a:1
      }
    }
    type A = ReturnType<typeof msgbox> //操作A
    type B = typeof msgbox("Are you sure you want to continue?"); //操作B
    

    但为了避免困惑,在typescript中,typeof只有被用于变量或者其属性,才被认为是合法行为,因此上述操作B会提示错误。这个是官网的表达,但也存在直接作用域字符串的情形与此表达相悖。

三、通过索引获取类型

索引一词,一般用于数组元素中,如根据下标索引,获取对应的元素。从概念上讲,只要能根据一个值A,能快速定位到另外一个值B,都可以说这个值A是值B的索引。下述示例中,需要注意一个概念,这是在typescript的类型系统中,所有的操作都是基于类型的

  • 普通对象

    type Person = { age: number; name: string; alive: boolean };
    type Age = Person["age"];
    

    如声明了一个类型Person,可以直接根据其属性作为键值,获取对应的属性值的类型。此时age并不是作为一个值,而是一个字面量类型

  • 数组

    type Person = { age: number; name: string; alive: boolean };
    type PersonArr = Array<Person>
    
    // type Example = PersonArr[0]
    type Example = PersonArr[number]
    

    在针对数组类型中,可以直接使用类型number获取元素类型,此时也可以传入具体的下标索引。因为是在操作类型,这些索引最终都会被转化为number类型。

  • 索引对象

    在普通对象中,可以直接使用属性名,快捷的获取类型,但在索引对象中,并不知道所有的类型。如下:

    type O = {
      [index:number]:boolean,
      do:number
    }
    type N = O["do"] // number
    type B = O[number] // boolean
    

    针对属性名称do,可以获取到类型number,这点和普通对象一致。但针对索引相关的属性,只需要提供一个number类型,便可以获取到对应的boolan类型,和数组类型一致。