Is it possible to create a typescript type from an array?

One built-in option would be to use an enum instead of the type and array approach.

export enum Stuff {
    something = 'something',
    else = 'else',
}

export const AVAILABLE_STUFF: Stuff[] = Object.values(Stuff);

Another option is to extract the type from the type of AVAILABLE_STUFF. To do this we must force the compiler to infer a tuple of string literals for AVAILABLE_STUFF. This can be done in 3.4 with as const or before 3.4 using an extra function. After AVAILABLE_STUFF is a tuple type we can just use a type query to get the type of the elements:

export const AVAILABLE_STUFF = (<T extends string[]>(...o: T)=> o)('something', 'else'); // typed as ["something", "else"]
// export const AVAILABLE_STUFF = ['something', 'else'] as const; // typed as ["something", "else"]  in 3.4
export type Stuff = typeof AVAILABLE_STUFF[number] //"something" | "else"

A few explanations of the above code. typeof AVAILABLE_STUFF gives us the type of the constant (["something", "else"]) to get the [number] is called a type query and will give us the type of an item in the tuple.

The (<T extends string[]>(...o: T)=> o) is just an IIFE we use to force the compiler to infer a string literal tuple type. It has to be generic as the compiler will only infer literal types and tuples in certain cases (a type parameter with a constraint of string being one of them). The as const version is what I would recommend using when it becomes available as it is more readable.


With TypeScript v3.4 const assertions:

export const AVAILABLE_STUFF = <const> ['something', 'else'];
export type Stuff = typeof AVAILABLE_STUFF[number];

Another possibility is to create an object and use keyof. I recommend that way only if you have anything useful to store as values (in replacement of null in the code below).

const stuffDict = {
  something: null,
  else: null,
}

type Stuff = keyof typeof stuffDict
const AVAILABLE_STUFF = Object.keys(stuffDict) as Stuff[]