Encountering a rather peculiar scenario with TypeScript. I have made efforts to create a concise example to allow easy testing in the TypeScript Playground.
- A type named
BaseA
exists, which may possess different structures based on one of its type arguments. - There is also a type labeled
DFunction
, representing a function that accepts objects of typeBaseA
. - The return type of
DFunction
should vary depending on the type ofBaseA
received by it.
type BaseA<P, Special=false> = {
payload: P;
} & Special extends true ? {_special:true} : {};
type DFunction = {
<A extends BaseA<any, false>>(a: A): A;
<A extends BaseA<any, true>>(a: A): Promise<A>;
};
function test(
d: DFunction,
normalA: BaseA<{x:number}, false>,
specialA: BaseA<{x:number}, true>
) {
// As we pass a `specialA` to `d`, the expected return type should be a Promise.
d(specialA).then(() => {});
}
Encountering an error on the last line due to TypeScript not recognizing that d(specialA)
returns a Promise. How can I define DFunction
in a way that links its return type to its input type?
It's worth mentioning that this approach works for simpler examples:
type DFunction = {
<A extends string>(a: A): A;
<A extends number>(a: A): Promise<A>;
};
function test(
d: DFunction
) {
d(5).then(() => {}); // no errors
const b = d("5"); // `b` inferred as type `string`
}