MST
星途 面试题库

面试题:TypeScript 函数参数与返回值类型的泛型及逆变协变应用

设计一个 TypeScript 通用函数,它可以接收一个函数作为参数,这个传入的函数的参数类型是一个泛型 `T`,返回值类型是 `T` 的子类型(使用逆变和协变相关知识)。你所设计的通用函数需要返回一个新函数,新函数接收与传入函数相同类型的参数,并返回与传入函数相同类型的返回值,但要在执行传入函数前后打印一些日志信息。请详细说明类型设置及其中涉及的逆变协变原理。
25.8万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试
// 定义通用函数
function withLogging<T, U extends T>(fn: (arg: T) => U): (arg: T) => U {
    return function (arg: T): U {
        console.log('Before function execution');
        const result = fn(arg);
        console.log('After function execution');
        return result;
    };
}

// 示例函数
function multiplyByTwo(num: number): number {
    return num * 2;
}

const loggedMultiplyByTwo = withLogging(multiplyByTwo);
const result = loggedMultiplyByTwo(5);
console.log(result);

类型设置说明

  1. T 泛型:表示传入函数 fn 参数的类型。
  2. U extends T 泛型:表示传入函数 fn 返回值的类型,UT 的子类型,这确保了返回值类型与参数类型之间的关系符合协变规则。
  3. 函数参数 fn: (arg: T) => U:定义了传入函数 fn 的类型,它接受类型为 T 的参数并返回类型为 U 的值。
  4. 返回函数 (arg: T) => U:新返回的函数接受与传入函数相同类型 T 的参数,并返回与传入函数相同类型 U 的返回值。

逆变协变原理

  1. 协变(Covariance):在 withLogging 函数中,返回值类型 UT 的子类型,这体现了协变。当 fn 返回 U 类型的值时,新返回的函数也返回 U 类型的值,满足协变规则,即子类型的返回值可以替代父类型的返回值。
  2. 逆变(Contravariance):这里虽然没有直接体现逆变,但如果考虑更复杂的场景,例如函数作为参数传递给其他函数时,如果一个函数接受的参数类型是父类型,那么传递一个接受子类型参数的函数是符合逆变规则的。在这个例子中,传入函数 fn 接受 T 类型参数,新返回函数也接受 T 类型参数,没有改变参数类型的父子关系,所以不涉及逆变的特殊处理,但在理论上理解逆变与协变在函数类型中的应用是重要的。