简体   繁体   中英

how do I create a narrow type based on an objects values

I'm in the process of moving from flow to typescript and I've run into something I can't figure out how to do. In flow I had the following:

const color = Object.freeze({
  white: '#ffffff',
  black: '#000000',
})

type PossibleColorValues = $Values<typeof color>

in this case PossibleColorValues was '#ffffff' | '#000000' '#ffffff' | '#000000'

Is there an equivalent to this in typescript? I've tried the following:

type PossibleColorValues = typeof color[keyof typeof color]

but in this case PossibleColorValues is just string

You have the right idea about how to get a union of all possible values in an object. typeof color[keyof typeof color] should do the trick.

The problem is that color does not preserve original types as it is currently defined. You need to convince the compiler to preserve the string literal types you originally assign in the object literal.

In 3.4, unreleased yet, you can use as const to let the compiler know you want literal types and a readonly object. So this will work as expected in 3.4 (again when 3.4 is released probably this month):

const color = Object.freeze({
  white: '#ffffff',
  black: '#000000',
} as const)

type PossibleColorValues = typeof color[keyof typeof color]

In the meantime you can use a function to get the compiler to infer literal types:

declare function withLiterals<
    T extends Record<string, V>, 
    V extends string | boolean | number | symbol | null | undefined | Record<string, V>
>(input: T ): T;

const color = Object.freeze(withLiterals({
    white: '#ffffff',
    black: '#000000',
}));

type PossibleColorValues = typeof color[keyof typeof color] 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM