7

Consider the following code:

type Foo = "Foo" | "Bar" | "Baz"

function isInFoo(str: string) boolean {
    // return Foo.contains(str); ?
}

In typescript, is there an elegant way to check if str is in type Foo?

jmrah
  • 5,715
  • 3
  • 30
  • 37

2 Answers2

3

Type annotations are removed from compiled code and are not available at runtime. But to expand on Ivan's answer, here is an example of extracting typed data from an array:

const fooBar = ['foo', 'bar', 'baz'] as const;
type FooBar = typeof fooBar[number]; // "foo" | "bar" | "baz"

Then you can write a custom type guard that checks a string at runtime:

function isFooBar(string: unknown): string is FooBar {
    return typeof string === 'string' && string in fooBar;
}

And use it like this:

const maybeFooBar: unknown = 'baz';
if (isFooBar(maybeFooBar)) {
    console.log('Typescript knows this is a FooBar');
}
jtschoonhoven
  • 1,948
  • 1
  • 19
  • 16
  • 1
    I added a more in-depth answer here: https://stackoverflow.com/a/61129291/3076390 – jtschoonhoven Apr 09 '20 at 20:45
  • 1
    isFooBar will return false since `string in fooBar` will return false as per https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in#examples – Clanket Apr 05 '23 at 19:12
  • @Clanket is correct here, the `in` operator checks for the existence of keys, not values. So `0 in fooBar`, `1 in fooBar`, `2 in fooBar` will return `true`, but `string in fooBar` will always return `false` if `typeof string === 'string'` is `true` – nathanhleung May 31 '23 at 04:36
1

type Foo will not be compiled into the generated javascript. It can not be realized in an elegant way. As one option: use an array with the specified strings, or get at these fields through an enum.

Paarth
  • 9,687
  • 4
  • 27
  • 36
Ivan Antonov
  • 51
  • 1
  • 7