面试题答案
一键面试设计思路
- 为了处理函数参数的逆变和协变关系,我们需要使用泛型。通过泛型来表示传入函数的参数类型和返回值类型。
- 利用
infer
关键字在条件类型中推断传入函数的参数类型和返回值类型。 - 使用剩余参数
...args
来接受任意数量的其他参数,并确保这些参数类型与传入函数的参数类型匹配。
代码示例
type FirstArgument<T extends (...args: any[]) => any> = T extends (arg: infer A, ...args: any[]) => any ? A : never;
type RestArguments<T extends (...args: any[]) => any> = T extends (arg: any, ...args: infer R) => any ? R : never;
type ReturnTypeOf<T extends (...args: any[]) => any> = T extends (...args: any[]) => infer R ? R : never;
function callFunction<T extends (...args: any[]) => any>(func: T, ...args: [...[FirstArgument<T>], ...RestArguments<T>]): ReturnTypeOf<T> {
return func.apply(null, args);
}
// 示例使用
function add(a: number, b: number): number {
return a + b;
}
const result = callFunction(add, 1, 2);
console.log(result); // 输出: 3
在上述代码中:
FirstArgument
类型别名用于推断传入函数的第一个参数类型。RestArguments
类型别名用于推断传入函数除第一个参数外的其他参数类型。ReturnTypeOf
类型别名用于推断传入函数的返回值类型。callFunction
函数接受一个函数func
和剩余参数...args
,并确保参数类型匹配,同时正确返回函数执行结果,其类型与传入函数的返回值类型一致。