🌙 keyof
关键字
keyof
与Object.keys
略有相似,只是 keyof
是取 interface
的键,而且 keyof
取到键后会保存为联合类型
。
interface IUserInfo {
name: string;
age: number;
}
function getValue<T extends Object, K extends keyof T>(o: T, key: K): T[K] {
return o[key];
}
const obj1 = {name: 'xx', age: 18};
const a = getValue(obj1, 'name');
// name、age
type keys = keyof IUserInfo;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
🌙 in
关键字
用于取联合类型的值。主要用于数组和对象的构造。
type name = 'firstName' | 'lastName';
type TName = {
[key in name]: string;
}
1
2
3
4
5
2
3
4
5
🌙 infer
关键字
推断类型:
- 只能出现在有条件类型的
extends
子语句中; - 出现
infer
声明,会引入一个待推断的类型变量; - 推断的类型变量可以在有条件类型的
true
分支中被引用; - 允许出现多个同类型变量的
infer
🌙 获取函数参数 Parameters
type TArea = (width: number, height: number) => number;
type MyParameters<T extends (...args: any[]) => any> = T extends (...args: infer P) => any ? P : never;
type params = Parameters<TArea>;
1
2
3
4
5
2
3
4
5
🌙 获取函数ReturnType
type MyReturnType<T extends (...args: any[]) => any> = T extends (...args: any[]) => infer R ? R : any;
type returnType = ReturnType<TArea>
1
2
3
2
3
🌙 获取实例类型 InstanceType
type MyInstanceType<T extends new (...args: any[]) => any> = T extends new (...args: any[]) => infer R ? R : any;
1
🌙 获取构造函数类型ConstructorParameters
type MyConstructorParameters<T extends new (...args: any[]) => any> = T extends new (...args: infer P) => any ? P : never;
1
🌙 获取参数 this 参数 ThisParameterType
type MyThisParameterType<T> = T extends (this: infer U, ...args: any[]) => any ? U : unknown;
1
以上均存在内置类型:
Parameters
获取函数参数类型
ReturnType
获取函数返回类型
InstanceType
获取实例类型
ConstructorParameters
获取构造函数参数类型
ThisParameterType
获取函数this类型
OmitThisParameter
剔除 this 参数
🌙 练习1
假设有一个这样的类型:
interface initInterface {
count: number;
message: string;
asyncMethod(input: Promise<string>): Promise<Action<number>>;
syncMethod(action: Action<string>): Action<number>;
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
在经过 Connect 函数之后,返回值类型为:
interface Result {
asyncMethod(input: string): Action<number>;
syncMethod(action: string): Action<number>;
}
1
2
3
4
5
2
3
4
5
其中 Action<T>
的定义为:
interface Action<T> {
payload?: T
type: string
}
1
2
3
4
2
3
4
现在要求写出Connect
的函数类型定义。
答案:
type ans = Connect<initInterface>
// 非函数属性去除
type RemoveNonFunctionProps<T> = {
[K in keyof T]: T[K] extends Function ? K : never;
}[keyof T]
// 将只包含函数属性的类型Pick出来
type PickFunction<T> = Pick<T, RemoveNonFunctionProps<T>>;
type TransformMethod<T> = T extends (
input: Promise<infer U>
) => Promise<Action<infer S>>
? (input: U) => Action<S>
: T extends (action: Action<infer U>) => Action<infer S>
? (action: U) => Action<S>
: never;
type ConnectAll<T> = {
[K in keyof T]: TransformMethod<T[K]>;
};
type Connect<T> = ConnectAll<PickFunction<T>>;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
🌙 练习2
有原数组如下:
const data1 = [
{
a1: 'a',
b1: 'b',
c1: 'c'
}
];
1
2
3
4
5
6
7
2
3
4
5
6
7
请实现transformData
const A1 = transformData(data1, {a1: 'a2'}); // 返回 [{a2: 'a'}]
const A2 = transformData(data1, {a1: 'a2', b1: 'b2'}); // 返回 [{a2: 'a', b2: 'b']
1
2
2
做了两件事儿:
- 1.替换
key
- 2.过滤掉没有被替换的
key
答案:
interface Item {
[K: string]: string
}
function transformData<T extends Object>(arr: T[], obj: Partial<T>) {
// 先替换key再过滤
return arr.map(item => {
// 获取ikeys
let itemKeys = Object.keys(item);
let objKeys = Object.keys(obj);
let newObj = {};
// 替换key
objKeys.forEach(ok => {
itemKeys.forEach(ik => {
if (ok === ik) {
newObj[obj[ok]] = item[ik]
}
})
})
return newObj;
})
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23