我试图定义一个可以包装任意函数的函数,同时保留参数类型和返回类型.我让它在函数没有泛型的情况下工作,但我很难让它与泛型一起工作.下面是一个简化的例子:

function wrap<F extends (...args: any[]) => any>(test: F) {
  return (...args: Parameters<typeof test>): ReturnType<typeof test> => {
    return test(...args);
  };
}
function simpleTest(a: number): number {
  return a;
}

// works
// type: (a: number) => number
const wrappedSimpleTest = wrap(simpleTest);
function genericTest<T>(a: T): T {
  return a;
}

// doesn't work
// type: (a: unknown) => unknown
// desired type: <T>(a: T) => T
const wrappedGenericTest = wrap(genericTest);
function genericTest2<T, U>(a: T, b: U): T|U {
  return Math.random() < 0.5 ? a : b;
}

// doesn't work
// type: (a: unknown, b: unknown) => unknown
// desired type: <T, U>(a: T, b: U) => T|U
const wrappedGenericTest2 = wrap(genericTest2);

推荐答案

您在这里寻找的特定行为可以通过使用microsoft/TypeScript#30215中实现的TypeScript的support for higher order type inference from generic functions来实现.一般来说,语言不能在类型系统中以这种方式抽象泛型;按照microsoft/TypeScript#1213中的要求,这需要higher kinded types个字符,而TypeScript没有.相反,它使用一些具有特定限制和要求的启发式方法,试图以这种方式推断通用函数类型.

有一种方法可以让它工作:

function wrap<A extends any[], R>(test: (...args: A) => R) {
  return (...args: A): R => {
    return test(...args);
  };
}
    
const wrappedGenericTest = wrap(genericTest);
// const wrappedGenericTest: <T>(a: T) => T ????

const wrappedGenericTest2 = wrap(genericTest2);
// const wrappedGenericTest2: <T, U>(a: T, b: U) => T | U ????

我用一对与参数和返回类型对应的类型参数AR替换了F类型参数.这里使用F的问题是,the Parameters<T> utility typethe ReturnType<T> utility typeconditional types,编译器无法跟踪泛型.

通过直接使用AR,编译器可以跟踪高阶类型操作,并获得所需的通用函数类型.

Playground link to code

Typescript相关问答推荐

之间是否有区别:例如useEffect()React.useEffect()

react 路由6操作未订阅从react 挂钩表单提交+也不使用RTK查询Mutations

在动态对话框中使用STEP组件实现布线

使用axios在ngOnInit中初始化列表

如何在LucideAngular 添加自定义图标以及如何使用它们

TypeScrip-将<;A、B、C和>之一转换为联合A|B|C

TypeScrip:逐个 case Select 退出noUncheck kedIndexedAccess

Angular NgModel不更新Typescript

为什么我的查询钩子返回的结果与浏览器的网络选项卡中看到的结果不同?

如何编写在返回函数上分配了属性的类型安全泛型闭包

正交摄影机正在将渲染的场景切成两半

APP_INITIALIZER在继续到其他Provider 之前未解析promise

基元类型按引用传递的解决方法

(TypeScript)TypeError:无法读取未定义的属性(正在读取映射)"

我在Angular 17中的environment.ts文件中得到了一个属性端点错误

从非文字数组(object.keys和array.map)派生联合类型

17个Angular 的延迟观察.如何在模板中转义@符号?

可以将JS文件放在tsconfig';s includes/files属性?或者,我如何让tsc判断TS项目中的JS文件?

使用NextJS中间件重定向,特定页面除外

如何向我的自定义样式组件声明 custom.d.ts ?