In this type case, What should the test() function's generic should be?
interface A {
type: 'a' ;
state: number;
}
interface B {
type :'b',
state: string;
}
type OneOfThem = A | B;
function test<T extends OneOfThem>(type: T['type'], state: T["state"]): T {
return {type, state} as T
}
test('a', 3) // should not be error
test('a', "asd") // should be error
In this case, test function's type are working like
function test<OneOfThem>(type: "a" | "b", state: string | number): OneOfThem
so both of expressions does not throw errors.
One possible way to distiguish between either of the Union Members is by using a Conditional Type. Here's one approach using the built in type Extract
. Note, that here the generic is a subtype of OneOfThem["type"]
and not OneOfThem
.
interface A {
type: "a";
state: number;
}
interface B {
type: "b";
state: string;
}
type OneOfThem = A | B;
function test<T extends OneOfThem["type"]>(
type: T,
state: Extract<OneOfThem, { type: T }>["state"],
): Extract<OneOfThem, { type: T }> {
return { type, state } as Extract<OneOfThem, { type: T }>;
}
test("a", 3); // okay
test("a", "asd");
// ~~~~~ Argument of type 'string' is not assignable to parameter of type 'number'.
TypeScript Playground
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With