TypeScript:如何让嵌套函数通过链联合它们的类型

TypeScript: How to get nested functions to union their types through a chain

我想做的是创建一系列可以链接在一起的嵌套函数,最终回调的参数将是父函数的并集。到目前为止我失败的尝试示例:

TS Playground Link

export type SomeHandler<T> = (args: T) => void;

type WithFooArgs = { foo: string }
const withFoo = <T,>(handler: SomeHandler<T & WithFooArgs>) => (args: T & WithFooArgs) => handler(args);

type WithBarArgs = { bar: string }
const withBar = <T,>(handler: SomeHandler<T & WithBarArgs>) => (args: T & WithBarArgs) => handler(args);

type WithZooArgs = { zoo: string }
const withZoo = <T,>(handler: SomeHandler<T & WithZooArgs>) => (args: T & WithZooArgs) => handler(args);


export default withFoo(withBar(withZoo((args) => {
    // I want args to be type `WithFooArgs & WithBarArgs & WithZooArgs`
})));

我的目标是拥有一堆我可以用不同方式链接在一起的东西。

您正试图根据其周围的表达式更改 withZoo(..) 的泛型,这是不可能的。您可以创建一个接受这些 middleware-like 回调的单一泛型,然后使用来自这些回调的数据来键入一个回调函数,如下所示:

export type SomeHandler<T> = (args: T) => void;

type WithFooArgs = { foo: string }
const withFoo = <T,>(handler: SomeHandler<T & WithFooArgs>) => (args: T & WithFooArgs) => handler(args);

type WithBarArgs = { bar: string }
const withBar = <T,>(handler: SomeHandler<T & WithBarArgs>) => (args: T & WithBarArgs) => handler(args);

type WithZooArgs = { zoo: string }
const withZoo = <T,>(handler: SomeHandler<T & WithZooArgs>) => (args: T & WithZooArgs) => handler(args);

// 
type UnionToIntersection<U> = 
  (U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never;

function createHandler<Handler extends SomeHandler<any>>(handlers: Handler[], cb: (args: UnionToIntersection<Parameters<Parameters<Handler>[0]>[0]>) => void) {
    return (args: any) => {
        return cb(handlers.reduce((acc, cur) => cur(acc), args));
    };
}

export default createHandler([withFoo, withBar, withZoo], (args) => {
    console.log(args); // WithFooArgs & WithBarArgs & WithZooArgs
});

TypeScript Playground Link