TS类型操作之keyof & typeof & Indexed Access Types

1,573 阅读2分钟

概论

TS-类型操作.png

keyof

接受一个Object,生成Object的key的字符串的union(联合)

  • 用于普通对象:
type Point = { x: number; y: number };
type P = keyof Point; //p的值可以为 'x' | 'y'
const a:P = 'x'; 
const b:P = 1;  //Type '1' is not assignable to type 'keyof Point'.ts(2322)
  • 用于索引签名(index signature)对象:
type Arrayish = { [n: number]: unknown };
type A = keyof Arrayish; // type A = numbertype Mapish = { [k: string]: boolean };
type M = keyof Mapish; // type M = string | number 
// M可以为number的原因是,在对象的索引签名中,number会强制转化为string,如下面引用mapish的例子
const mapist: Mapish = {}
mapist[1] = false;
mapist['a'] = true;
  • 用于枚举类型
enum Colors {
    red,
    blue,
    yellow
}
type A = keyof Colors; // "toString" | "toFixed" | "toExponential" | "toPrecision" | "valueOf" | "toLocaleString"
//当把keyof用在number类型的enum上时,会得到Number.prototype上所定义的方法的名字(string格式)的联合类型。
enum Colors {
    red = 'red',
    blue = 'blue',
    yellow = 'yellow'
}
type A = keyof Colors; // number | "toString" | "charAt" | "charCodeAt" | "concat" | ...27 more... | "padEnd"
//当把keyof用在string类型的enum上时,我们就得到一个由number类型再加上String.prototype上定义的所有的方法的名字组成的一个联合类型。

typeof

在js语法中,typeof是获取类型,在ts中的应用则像将js语法转成ts语法

如下demo中A相当于type A = { x: number; y: number; }

const obj = { x: 10, y: 3 }
type A = typeof obj;
const a: A = {
    x:1,
    y:1
}

与ReturnType的结合:

function f() {
  return { x: 10, y: 3 };
}
type P = ReturnType<typeof f>; //type P = { x: number; y: number; }

Indexed Access Types

通过索引访问类型,其中有一个特殊的用法,是通过number对数组进行索引
我一直寻求一个准确的对Indexed Access Types的翻译,最终翻译为通过索引访问类型,如果你有好的翻译,欢迎评论区留言

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

假如通过“number”来索引数组对象时,其类似于union,即通过或连接所有的类型,需要注意的是,使用number遍历的是数组,是js语法,必须通过typeof转成ts,才可以定义在type中

const MyArray = [
    { name: "Alice", age: 15 },
    { name: "Bob", age: 23 },
    { name: "Eve", age: 38 },
    { name: 'Oli', age: 22, sex: 'M' }
];
type Person = typeof MyArray[number]; //type Person = { name: string; age: number; sex?: undefined; } | { name: string; age: number; sex: string; }
const p1: Person = { name: 'lin', age: 15 }
const p2: Person = { name: 'lin', age: 15, sex: 'F'}