TypeScript 给 JavaScript 加了套静态类型系统。其中,JavaScript 中的数组、对象等聚合多个元素的类型在 TypeScript 中对应的是索引类型。
1、映射类型
// 映射类型语法
// { readonly [P in K]?: T}
// { [P in K]: T}
// { [P in K]?: T}
// { [P in K]-?: T}
// { readonly [P in K]: T}
// { readonly [P in K] ?: T}
// { -readonly [P in K] ?: T}
//映射类型示例
type Item = { a: string; b: number; c: boolean; };
type T1 = { [P in 'x' | 'y']: number }; // {x: number; y: number}
type T2 = { [P in 'x' | 'y']: P }; // {x: ‘x' ; y: 'y'}
type T3 = { [P in 'a' | 'b']: Item[P] }; // {a: string ; b: number}
type T4 = { [P in keyof Item]: Item[P] }; // {a: string ; b: number, c: boolean}
2、实现工具类型
// 工具类型
type MyParital<T> = {
[P in keyof T]?: T[P]
};
type U1 = MyParital<{ name: string; age: number }>;// { name?: string; age?: number }
//例子:生成对象KV类型的getter函数类型
type Getter<T> = {
[K in keyof T as `get${Capitalize<K & string>}`]: () => T[K];
};
interface User {
name: string;
age: number;
choose: boolean;
};
type Getter1 = Getter<User>;
// {
// getName: () => string;
// getAge: () => number;
// getChoose: () => boolean;
// }
//例子:去除某一个key类型
type Exclude<T, K> = T extends K ? never : T;
type RemoveKindField<T> = {
[K in keyof T as Exclude<K, 'kind'>]: T[K];
};
interface User2 {
name: string;
age: number;
kind: 'kind'
};
type User3 = RemoveKindField<User2>;// {name: string; age: number}
3、keyof
keyof用法:
//keyof用法
// keyof用法示例
type K1 = keyof boolean; // 'valueof'
type K2 = keyof any;// string | number | symbol
type K3 = keyof number;// "toFixed" | "toExponential" | "toPrecision" | "toString" | "valueOf" | "toLocaleString"
type K4 = keyof string; // "charAt" | "charCodeAt" | "concat" | "indexOf" | "lastIndexOf" | "localeCompare" | "match" | "replace" | "search" | "slice" | "split" | ... 28 more ... | "valueOf"
enum HttpMethods {
Get,
Post,
Put,
Delete
};
type K5 = keyof typeof HttpMethods;// "Get" | "Post" | "Put" | "Delete"
Partial、Required、Pick、Record工具类型的内在实现
// 基于keyof实现的Partial、Required、Pick、Record工具类型的内在实现
type Partial<T> = {
[K in keyof T]?: T[K]
};
type Required<T> = {
[K in keyof T]-?: T[K];
}
type Pick<T, U extends keyof T> = {
[K in U]: T[K]
};
type Record<T extends keyof any, U> {
[key: T]: U;
}
keyof在泛型函数中的典型应用
type user5 = {
name: string;
age: number;
boo: boolean;
}
type ValueType<T, U> = T extends keyof U ? U[T] : never;
function fn3(obj: user5, key: keyof user5): ValueType<keyof user5, user5> {
return obj[key];
}
比如我们把一个索引类型的值变成 3 个元素的数组:
type MapType<T> = {
[Key in keyof T]: [T[Key], T[Key], T[Key]]
}
type res = MapType<{a: 1, b: 2}>;
/*
type res={
a:[1,1,1];
b:[2,2,2};
}
*/
除了值可以变化,索引也可以做变化,用 as 运算符,叫做重映射。
type MapType<T> = {
[
Key in keyof T as `${Key & string}${Key & string}${Key & string}`
]: [T[Key], T[Key], T[Key]]
}
/*
type res={
aaa:[1,1,1];
bbbb:[2,2,2};
}
这里的 & string 可能大家会迷惑,解释一下:
因为索引类型(对象、class 等)可以用 string、number 和 symbol 作为 key,这里 keyof T 取出的索引就是
string | number | symbol 的联合类型,和 string 取交叉部分就只剩下 string 了。就像前面所说,交叉类型
会把同一类型做合并,不同类型舍弃。
*/
原文链接: