// 定义通用函数
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);
类型设置说明
T
泛型:表示传入函数 fn
参数的类型。
U extends T
泛型:表示传入函数 fn
返回值的类型,U
是 T
的子类型,这确保了返回值类型与参数类型之间的关系符合协变规则。
- 函数参数
fn: (arg: T) => U
:定义了传入函数 fn
的类型,它接受类型为 T
的参数并返回类型为 U
的值。
- 返回函数
(arg: T) => U
:新返回的函数接受与传入函数相同类型 T
的参数,并返回与传入函数相同类型 U
的返回值。
逆变协变原理
- 协变(Covariance):在
withLogging
函数中,返回值类型 U
是 T
的子类型,这体现了协变。当 fn
返回 U
类型的值时,新返回的函数也返回 U
类型的值,满足协变规则,即子类型的返回值可以替代父类型的返回值。
- 逆变(Contravariance):这里虽然没有直接体现逆变,但如果考虑更复杂的场景,例如函数作为参数传递给其他函数时,如果一个函数接受的参数类型是父类型,那么传递一个接受子类型参数的函数是符合逆变规则的。在这个例子中,传入函数
fn
接受 T
类型参数,新返回函数也接受 T
类型参数,没有改变参数类型的父子关系,所以不涉及逆变的特殊处理,但在理论上理解逆变与协变在函数类型中的应用是重要的。