• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • 索引访问类型

    我们可以使用索引访问类型(indexed access type)查找另外一个类型上的特定属性:

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

    因为索引名本身就是一个类型,所以我们也可以使用|操作符、keyof操作符或者其他类型:

    type I1 = Person["age" | "name"];  
    // type I1 = string | number
    
    type I2 = Person[keyof Person];
    // type I2 = string | number | boolean
    
    type AliveOrName = "alive" | "name";
    type I3 = Person[AliveOrName];  
    // type I3 = string | boolean
    

    如果你尝试查找一个不存在的属性,TypeScript 会报错:

    type I1 = Person["alve"];
    // Property 'alve' does not exist on type 'Person'.
    


    接下来是对象数组示例:

    const MyArray = [
      { name: "Alice", age: 15 },
      { name: "Bob", age: 23 },
      { name: "Eve", age: 38 },
    ];
    
    console.log(MyArray);
    
    //数组 MyArray 的类型是:
    MyArray: {
        name: string;
        age: number;
    }[]
    

    数组MyArray是有三个对象组成的。每个键是数字类型number,每个值的类型是{name: string; age: number;}。所以MyArray[number]获得类型{name: string; age: number;},然后使用typeof捕获其的字面量

    type Person = typeof MyArray[number];
    /*type Person = {
        name: string;
        age: number;
    }*/
    
    type Age = typeof MyArray[number]["age"];
    //type Age = number
    
    type Age2 = Person["age"];
    //type Age2 = number
    

    作为索引的只能是类型,这意味着你不能使用const创建一个变量引用:

    const key = "age";
    type Age = Person[key];
    
    // Type 'key' cannot be used as an index type.
    // 'key' refers to a value, but is being used as a type here. Did you mean 'typeof key'?
    

    然而你可以使用类型别名实现类似的重构:

    type key = "age";
    type Age = Person[key];
    


    实例

    假设有这样一个业务场景,一个页面要用在不同的 APP 里,比如淘宝、天猫、支付宝,根据所在 APP 的不同,调用的底层 API 会不同,我们可能会这样写:

    const APP = ['TaoBao', 'Tmall', 'Alipay'];
    function getPhoto(app: string) {
        // ...
    }
    
    getPhoto('TaoBao');   // ok
    getPhoto('whatever');   // ok
    

    如果我们仅仅是对 app 约束为string类型,即使传入其他的字符串,也不会导致报错,我们可以使用字面量联合类型约束一下:

    const APP = ['TaoBao', 'Tmall', 'Alipay'];
    type app = 'TaoBao' | 'Tmall' | 'Alipay';
    
    function getPhoto(app: app) {
        // ...
    }
    
    getPhoto('TaoBao');   // ok
    getPhoto('whatever');   // not ok
    

    但写两遍又有些冗余,我们怎么根据一个数组获取它的所有值的字符串联合类型呢?我们就可以结合上一篇的typeof和本节的内容实现:

    const APP = ['TaoBao', 'Tmall', 'Alipay'] as const;
    type app = typeof APP[number];
    // type app = "TaoBao" | "Tmall" | "Alipay"
    
    function getPhoto(app: app) {
        // ...
    }
    
    getPhoto('TaoBao');   // ok
    getPhoto('whatever');   // not ok
    

    asconst将数组变为readonly的元组类型。

    上篇:typeof 操作符

    下篇:条件类型