1

I have some classes with a static variable indicating their type. I want to create a union type based on thoses static variables

class Foo {
  static typeId = 'i-am-foo';
}

class Bar {
  static typeId = 'i-am-bar';
}

type MyUnionType = Foo.typeId | Bar.typeId;

TS playground

Unfortunately this is not possible, I get the error

'Foo' only refers to a type, but is being used as a namespace here.

Is it possible to use static variables for type definitions?

baitendbidz
  • 187
  • 3
  • 19

1 Answers1

5

i-am-foo and i-am-bar are values, and not types and you are trying to access them and combine to create a union. To do that correctly, you will need to get the type of them using typeof.

Also, type your static values correctly using the right type. If you do not specify :

  static typeId :'i-am-foo'= 'i-am-foo';

the type of typeId would be the broad type string, and union of both string types will be string.

Note: One more way to do this would be:

  static typeId = 'i-am-foo' as const;

as const will tell TS to try and find the narrowest type.

Your code would look like:

class Foo {
  static typeId :'i-am-foo'= 'i-am-foo';
}

class Bar {
  static typeId : 'i-am-bar' = 'i-am-bar';
}

type MyUnionType = typeof Foo.typeId | typeof Bar.typeId;

Playground

Tushar Shahi
  • 16,452
  • 1
  • 18
  • 39
  • Nit: Using a [`const` assertion](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions) is probably a [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)er choice than a single [string literal](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types) type annotation in this case. – jsejcksn Nov 08 '22 at 08:12
  • @jsejcksn I have added both as you can see. But what is the reason I wonder for the preference? – Tushar Shahi Nov 08 '22 at 08:13
  • [^](https://stackoverflow.com/questions/74357301/is-it-possible-to-use-static-variables-for-type-definitions#comment131270360_74357461) Your initial answer didn't include it (but I see that you edited it in after I started composing my comment) — Neither prevents reassignment of the same value (e.g. `Foo.typeId = 'i-am-foo';`), but the const assertion more clearly indicates the intention, I think. – jsejcksn Nov 08 '22 at 08:16
  • 2
    @baitendbidz If you have a lot of classes with the same discriminant property, you can also use this syntax for the union in order to avoid repeating the property name each time: [`(typeof Foo | typeof Bar)['typeId']`](https://www.typescriptlang.org/play?noUncheckedIndexedAccess=true&target=99&jsx=4&useUnknownInCatchVariables=true&exactOptionalPropertyTypes=true#code/MYGwhgzhAEBiD29oG8BQ1oQC5iwS2GiwE8AHAUwEkATaAXmgHI8BaMAWxYDNFHpJoweADtsAblQBfVKlCQYAITAAnFOkw58hEhRr0mrDiwBGKvgKGisE6ah3loAWWIBVYXhEAVMg4YAKe3guOERoAB8iHyDoJWUASgBtRnsaRgBdCSA) – jsejcksn Nov 08 '22 at 08:22
  • @jsejcksn I found the other way of writing to be more clear tbh. But I think it is just a matter of preference. Definitely agree with the shortcut you have added in the 2nd comment. Would you want to edit the answer or should i add it? – Tushar Shahi Nov 09 '22 at 07:30
  • [^](https://stackoverflow.com/questions/74357301/is-it-possible-to-use-static-variables-for-type-definitions/74357461?noredirect=1#comment131294079_74357461) @TusharShahi Feel free: go for it. – jsejcksn Nov 09 '22 at 09:26