Search code examples
typescripttypesparameters

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