I have a simplified version of a more complex problem. The following causes TSC to throw errors:
type Demo<isTrue> = isTrue extends true ? { a: string } : isTrue extends false ? { b: string } : never;
const func = <T extends boolean>(arg: T): Demo<T> => {
if (arg) {
return {a: "hello" };
} else {
return { b: "world" };
}
};
const out = func(true);
Throws the following errors:
Type '{ a: string; }' is not assignable to type 'Demo<T>'.
Type '{ b: string; }' is not assignable to type 'Demo<T>'.
The out at the bottom has the correct type on inspection, so just the function definition has the issue. How can I understand this better and how do I solve it?
Take a look at this GitHub thread (also see the original issue). It boils down to the fact that TypeScript does not support the narrowing of function return types when using conditional types. Since the resolution of the
Demotype depends on a generic type parameterT, it is the same as if you wrote the conditional directly in the return type annotation.The issue should become clearer if we rewrite the
Demotype (for demonstration purposes only):Now it should be crystal clear that
D<T>remains unresolved until you provide an argument for the type parameter. That is whyconst out = func(true);is correctly inferred.You are pretty much limited to either using type assertions like
as Demo<T>or dropping the generic type parameter and rewriting the signature with overloads as outlined in captain-yossarian's answer.