0

I have array:

const someArray = ['one', 'two', 'three'];

and I have type:

type SomeType = 'one' | 'two' | 'three';

How can I get SomeType from someArray?

Igor Zvyagin
  • 454
  • 3
  • 13
  • It looks like this : [https://stackoverflow.com/questions/55020193/is-it-possible-to-create-a-typescript-type-from-an-array](https://stackoverflow.com/questions/55020193/is-it-possible-to-create-a-typescript-type-from-an-array) – JeromeBu Apr 02 '20 at 10:26

4 Answers4

3

You can, at the cost that you have to apply as const assertion to someArray.

const someArray = ['one', 'two', 'three'] as const;
                                       /* ^------- IMPORTANT!
                                          otherwise it'll just be `string[]` */

type GetItem<T> = T extends ReadonlyArray<infer I> ? I : never;

type SomeType = GetItem<typeof someArray>;  // 'one' | 'two' | 'three'
hackape
  • 18,643
  • 2
  • 29
  • 57
  • Just in case somebody is wondering. The above is only possible by changing the way `someArray` is defined, which is in a sense changing the premise of the question. I am leaving my answer down here so people may appreciate the fact that if you have a variable of type string array that there is in fact no way to retrieve the requested type. – Lodewijk Bogaards Jun 12 '20 at 20:35
1

You can not, because TypeScript is not a dependently-typed language.

TypeScript, like almost any other well known statically typed language in existence at the moment, can create types for values, but not create types from values.

So you can create a type for your values:

const someArray: SomeType[] = ['one', 'two', 'three'];

but you can not create a type from your values:

type SomeType = infer T for someArray[T] // invented syntax

Only dependently typed languages can do this. Unfortunately this is not yet mainstream. Give it another decade though and you'll be hearing more about this.

Probably this does not mean you are stuck though. Over time I've had very few times where I could absolutely not get to the type just because the language was not dependently typed. You should try to ask another question and might get a satisfactory answer. There are ways for example to have types available during runtime, like with https://github.com/gcanti/io-ts.

Lodewijk Bogaards
  • 19,777
  • 3
  • 28
  • 52
  • 1
    For this case it's actually possible in TS, see my answer. Good resources linked though. – hackape Apr 02 '20 at 15:01
  • 1
    Nice, I didn't know that trick! It will of course only work if the array is defined as a literal constant (as the example is). For runtime defined arrays the only way to achieve the result is through dependent typing, so I'll leave my answer here and upvote yours. – Lodewijk Bogaards Apr 06 '20 at 07:50
1

I found an even simpler solution.

const someArray = ['one', 'two', 'three'] as const;
                                       /* ^------- IMPORTANT!
                                          otherwise it'll just be `string[]` */

type SomeType = typeof someArray[number];  // 'one' | 'two' | 'three'
Igor Zvyagin
  • 454
  • 3
  • 13
-1

by 'filter' to ergodic return satisfy condition‘s element

zht
  • 7
  • 1