I have type narrow problem. how to narrow type of parameter v to successfully pass it ot funcAorB?
// type.d.ts
export type A = "A1" | "A2";
export type B = "B1" | "B2";
export type U = A | B;
export function funcAorB(v: A) : A;
export function funcAorB(v: B) : B;
// test.ts
function wrappFunAorB<T extends U>(v:T) {
type V<K> = K extends A ? A : B;
funcAorB(v as V<T>) // error
}
I expected V<T>
would narrow type of T but is didn't
Since you've defined funcAorB
using overloads, TypeScript needs to know which specific overload to call (even though either way, it ends up calling the same implementation function). That is, it has to know whether the runtime v
will be an A
or a B
. A compile-time check won't work.
You have at least two choices:
Implement a type predicate to narrow v
, for instance:
function isA(value: any): value is A {
return value === "A1" || value === "A2"; // Just an example, you probably want something more robust, where the check and the type have the same single source
}
...and then use logic so TypeScript sees a narrowed type, for instance:
function wrappFunAorB<T extends U>(v :T) {
if (isA(v)) {
funcAorB(v);
} else {
funcAorB(v);
}
}
Implement the function accepting a union type instead, rather than using overloads. It can either directly accept the union:
function funcAorB(v: A | B): A | B {
// ...
}
Or it can use a generic type parameter:
function funcAorB<T extends A | B>(v: T): T {
// ...
}