Home > Net >  TypeScript Type union not working as expected
TypeScript Type union not working as expected

Time:12-31

I wonder why the following does not work:

const GUEST = 0;
const ADMIN = 1;
type Role = typeof GUEST | typeof ADMIN;

const filterPerRole = (
    users: any[],
    role: Role,
): any[] => users.filter(user => user.role === role);

[GUEST, ADMIN].map(role => filterPerRole([], role)); 

I get the following error on the second argument of filterPerRole:

Argument of type 'number' is not assignable to parameter of type 'Role'.

The following does not fails though:

const guestUsers = filterPerRole([], GUEST)
const admintUsers = filterPerRole([], ADMIN)

I find it a bit confusing that I have to explicitly cast again to make it work:

[GUEST, ADMIN].map(role => filterPerRole([], role as Role));

CodePudding user response:

Typescript infers the type of [GUEST, ADMIN] to number[] - it is a mutable array of numbers.

You can force the array to be treated as constant - [GUEST, ADMIN] as const. The inferred type is readonly [0, 1]

Thus, you can change your code to the following:

const roles = [GUEST, ADMIN] as const;
roles.map(role => filterPerRole([], role)); 

An alternative is to give explicit type to the array:

const roles: Role[] = [GUEST, ADMIN];
roles.map(role => filterPerRole([], role)); 

On top of that: the title is not correct. A | B is an UNION of A and B, not intersection.

Playground link

  • Related