1

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

  • 2
    A `Set` is a class that you need to instantiate and you cannot just assign an array to a property that is one. – crashmstr Oct 28 '21 at 21:23
  • Do you want a set or an array? How many entries will your enum have? If it's more than about 8 you can't represent "all possible exhaustive arrays without duplicates" as a specific type and you'd instead have to use a generic type instead, so `SomeInterface` would become `SomeInterface`. I think we need more info here to be able to answer. – jcalz Oct 28 '21 at 21:34

1 Answers1

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