Declaration of an array with unique values

I need some like this if it's possible

export enum Roles {
  Role1 = 'Role1',
  Role2 = 'Role2',
}

export interface SomeInterface {
  permissions: Set<Roles>;
}

const someInterface: SomeInterface = {
  // values must be unique, if there are duplicates, typescript should warn about it
  permissions: [Roles.Role1, Roles.Role2],
}

enter image description here

I would be glad to get any tips, because I could not solve this typing problem myself

Upvotes: 1

Views: 1091

Answers (1)

You can use this type:

export enum Roles {
  Role1 = 'Role1',
  Role2 = 'Role2',
}
// credits goes to https://twitter.com/WrocTypeScript/status/1306296710407352321
type TupleUnion<U extends string, R extends any[] = []> = {
  [S in U]: Exclude<U, S> extends never ? [...R, S] : TupleUnion<Exclude<U, S>, [...R, S]>;
}[U];


export interface SomeInterface {
  permissions: TupleUnion<keyof typeof Roles>;
}

const someInterface: SomeInterface = {
  permissions: [Roles.Role1, Roles.Role2] // ok
}

const someInterface2: SomeInterface = {
  permissions: [Roles.Role1, Roles.Role1] // error
}

Playground

Please be aware that it will heat your PCU if there will be a lot of keys in your enum or fails if it hits recursion limit. TupleUnion creates a union of all possible permutations of the tuple. Here you can find an explanation how this works

Upvotes: 2

Related Questions