function spread parameters should not be repeated in typescript

I am creating a function that takes some roles in an Enum, I want the parameters not to be repeated.

type Role = 'ADMIN' | 'GUEST'

function roleMiddleware(...roles: Role[]){
  // some logic
}
roleMiddleware('ADMIN', 'ADMIN'); // I shouldn't be able to do that

Is this achievable ? and if so how should I type the parameters of that function to achieve such behavior?

>Solution :

Taking some inspiration from Is there a way to define type for array with unique items in typescript?, we can achieve the following:

type Invalid<T> = Error & { __errorMessage: T };

type Valid<Roles extends Role[]> = {
  [K in keyof Roles]: unknown extends {
    [P in keyof Roles]: K extends P ? never : Roles[P] extends Roles[K] ? unknown : never;
  }[keyof Roles]
    ? Invalid<[Roles[K], "is repeated"]>
    : Roles[K]
}

function roleMiddleware<Roles extends Role[]>(...roles: Valid<Roles>) { ... }

For a detailed in-depth explanation, see linked question above.

Playground

Leave a Reply