如何合并Foo <a> | Foo<b> into Foo</b></a> <b> <a |="" b="">

时间:2018-06-06 09:10:39

标签: typescript

I fell into a case where I have the following variable :

var foo: Foo<string> | Foo<number> | Foo<boolean>;

generated dynamically (using keyof and stuff), which is fully intended at that point of the code. But then, I need to call methods inside that object defined like this :

class Foo<T> {
    pipe(): Foo<T>;
    pipe<A, B>(obj: Operator<T, A>, obj2: Operator<A, B>): Foo<B>;
    pipe<A>(obj: Operator<T, A>): Foo<A>;
    pipe(...obj: Operator[]): Foo<any> {
        return new Foo();
    }
}

The problem being, when I do the following :

const f = foo.pipe((bar) => new Foo());

bar is infered as string while I'd expect string | number | boolean.

My guess here is that I need to convert Foo<string> | Foo<number> | Foo<boolean> into Foo<string | number | boolean> where it solves the problem.

How can I do such convertion ?

1 个答案:

答案 0 :(得分:4)

您可以使用条件类型来实现此目的(联合类型分布在联盟上,在这种情况下可以帮助我们)

type UnionOfFooToFooOfUnion<T extends Foo<any> > = Foo< T extends Foo<infer U> ? U : never>

let foo!: Foo<string> | Foo<number> | Foo<boolean>;

let merged: UnionOfFooToFooOfUnion<typeof foo> =  foo // we can just assign it 

或者我们可以使用一个函数:

function mergeFoo<T extends Foo<any>>(foo: T): UnionOfFooToFooOfUnion<T> {
    return foo;
}
mergeFoo(foo).pipe(s=> console.log(s)) // s is number | string | boolean