3

I have the type:

export type PermissionType = 'creator' | 'editor' | 'viewer' 

At run time, how to check if a variable userInput is actually one the type above

let userInput = 'foo' //
isOfTypePermission(userInput)  // should return false or throw an error

let userInput2 = 'creator'
isOfTypePermission(userInput2) // should return true

In other word, how to get the type PermissionType compiled into a javascript array so that I can just do indexOf(userInput) > -1

TSR
  • 17,242
  • 27
  • 93
  • 197

1 Answers1

24

Don't over-complicate it.

function isOfTypePermission (userInput: string): userInput is PermissionType {
  return ['creator', 'editor', 'viewer'].includes(userInput);
}

See What does the `is` keyword do in typescript? for more information on why we don't just use a boolean return type.

If your PermissionType is really long, then it might be worth it to infer the type from a const value instead.

const permissions = ['creator', 'editor', 'viewer'] as const;
type PermissionType = (typeof permissions)[number];

function isOfTypePermission (userInput: string): userInput is PermissionType {
  return (permissions as readonly string[]).includes(userInput);
}

Or possibly even a Set

const permissions = new Set(['creator', 'editor', 'viewer'] as const);
type PermissionType = typeof permissions extends Set<infer T> ? T : never;

function isOfTypePermission (userInput: string): userInput is PermissionType {
  return (permissions as Set<string>).has(userInput);
}
Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
  • This is why I love algebraic types and I wish other languages supported it too! – Dai Jul 16 '19 at 21:30
  • 3
    Is there something generic/dynamic for that, Because in that particular case the list could be updated and need to remember updating it. – Ido Bleicher Dec 27 '20 at 10:06
  • @Bleicher The question was about a type which is a string literal union. Sounds like you wouldn't be able to actually restrict the type if you determined the value was contained in a list which is runtime dynamic. You'd still only know that it was a `string`. – Patrick Roberts Dec 27 '20 at 19:46