Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to type a function of union type's each properties

Tags:

typescript

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.

like image 336
FourwingsY Avatar asked Oct 11 '25 23:10

FourwingsY


1 Answers

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

like image 197
Behemoth Avatar answered Oct 15 '25 15:10

Behemoth