typescript 索引和映射类型

86 阅读2分钟

类型层级

捕获.JPG

infer

infer是inference的缩写,用来在条件类型中提取类型的某些信息。 infer只能在函数类型结构和条件类型中使用,例如

type FunctionReturnType<T extends Func> = T extends ( ...args: any[] ) => infer R ? R : never;

索引签名类型

在接口或者类型别名中,声明一个键值类型一致的类型结构

interface stringTypes {
  [key: string]: string // 类型结构变量中只能声明字符串类型的键
}

索引签名类型里具体的键值类型需要符合索引签名类型的声明

 interface stringtTypes {
    prop: number; //类型“number”的属性“prop”不能赋给“string”索引类型“string”
    [key: string]: string 
  }

由于在javascript中,会将数字索引访问转换为字符串索引访问,所以在字符串索引签名中可以声明数字类型和symbol的键

interface stringtTypes {
   'age': '1',
   1: 'age',
   [key: string]: string
  }

keyof 索引类型查询

关键字,用于获取一个类型的所有键的联合类型

  interface userInfo {
    name: string;
    age: number;
    12
  }

  type key = keyof userInfo; // 'name' | 'age' | 1 数字类型的键名不会转换为字符串类型字面量
  
  //操作类
  class User {
    name: string = 'name1'
  }
  let sname: keyof User = 'name'

泛型中keyof的使用

  interface UserInfo {
    name: string;
    age: number;
  }
  class User {
    constructor(private user: UserInfo) {}
    // getInfo(key: string) {
    //   if (key === 'name' || key === 'age') {
    //     return this.user[key]
    //   }
    // }
    // key值不做校验,没有限制任意传值,导致程序报错;加上if校验,传入name和age以外的值,程序只会返回undefined
    getInfo<T extends keyof UserInfo>(key: T): UserInfo[T] {
      return this.user[key];
    }
    // T extends keyof UserInfo 限定参数范围 name,age
    // key:T 类中的属性 (name,age)
    // UserInfo[T] 返回对象中的属性值
  }

索引类型访问

通过键的字面量类型访问键对应的键值类型

interface numberTypes {
    [key: string]: number
    prop: number
  }
  type propType = numberTypes[string] // number 未定义索引签名类型不能使用原始类型访问
  type numbers = numberTypes['prop'] // number

映射类型

in关键字 基于键名映射到键值类型

  type example<T> = {
    [K in keyof T]: T[K]
  }
  type stringify<T> = {
    [K in keyof T]: string 
  }
  interface user {
    name: string;
    age: number;
    prop: () => void
  }
  type stringifyUser = stringify<user>
//   等价于
//   interface stringifyUser {
//     name: string;
//     age: string;
//     prop: void
//   }

模板字面量类型

以字符串字面量类型为基础,通过联合类型扩展成多个字符串,只能在类型定义中使用,模板字面量类型中的变量只能说原始类型string、number、bigint、boolean、null、undefined或这些类型的联合类型。

  1. 基本语法
type actions = 'add' | 'remove';

type property = 'name' | 'age';

type result = `${actions}${Capitalize<property>}`; // type result = addName | addAge | removeName | removeAge
  1. 类型推断
type Direction = 'left' | 'right' | 'top' | 'bottom';

type InferRoot<T> = T extends `${infer K}${Capitalize<Direction>}` ? K : T;

type Result1 = InferRoot<'marginRight'>; // type Result1 = 'margin';

type Result2 = InferRoot<'paddingLeft'>; // type Result2 = 'padding';