How to type an array’s values with Typescript

In the code below I am retrieving each key from an object, removing the digits and duplicates and then I store them in an array. I’d like to use that array as a type.

Here’s what the color object looks like.

const color = {
    blue100: '#...',
    blue500: '#...',
    red100: '#...',
    red500: '#...',
    yellow100: '#...',
    yellow500: '#...',
    ...
}

Here’s what I came up with so far

const colorChars = Object.keys(color).map((x) => x.replace(/[0-9]/g, ''))
const colorArray = [...new Set(colorChars)]
const colorNames = colorArray as const

export type ColorNameType = typeof colorNames
// expected: type ColorNameType = 'blue' | 'red' | 'yellow'

Here’s the error I get

A 'const' assertions can only be applied to references to enum members, or string, number, boolean, array, or object literals.

The error disappears if I wrap colorArray like so [...colorArray] but it doesn’t solve the issue because the type stays as String[]. Any idea on how to solve this or is there another attractive work around?

Answer

If you need to convert object keys to union type you can simply use keyof typeof YourConstObject like this:

const color = {
    blue100: '#1',
    blue500: '#2',
    red100: '#3',
    red500: '#4',
    yellow100: '#5',
    yellow500: '#6',
} as const;

type Keys = keyof typeof color;//"blue100" | "blue500" | "red100" | "red500" | "yellow100" | "yellow500"

Or if you need to create union type with values of object you can do like this:

type ValueOf<T> = T[keyof T]

type values = ValueOf<typeof color>//"#1" | "#2" | "#3" | "#4" | "#5" | "#6"

PlaygroundLink

But note that whenever you try to manipulate the object keys like using map, push, replace so ts compiler have face with string[] type because it does not make sense for the compiler your new array, like: blue, red....