Btw, if you are interested in HEX type safety, you can try next approach:
type HexNumber = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
type HexString = 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f'
type StringNumber<T extends number> = `${T}`;
type HEX = HexNumber | StringNumber<HexNumber> | HexString;
type ToArray<T extends string, Cache extends readonly string[] = []> =
T extends `${infer A}${infer Rest}`
? A extends HEX
? ToArray<Rest, [...Cache, A]> : A extends ''
? 1 : 2 : T extends '' ? Cache extends { length: 6 }
? Cache : 'String should have 6 chars. No more, no less' : never;
type Elem = string;
type ReduceToString<
Arr extends ReadonlyArray<Elem>,
Result extends string = ''
> = Arr extends []
? Result
: Arr extends [infer H]
? H extends Elem
? `${Result}${H}`
: never
: Arr extends readonly [infer H, ...infer Tail]
? Tail extends ReadonlyArray<Elem>
? H extends Elem
? ReduceToString<Tail, `${Result}${H}`>
: never
: never
: never;
const colors = {
red: '#ff0000',
green: '#00ff00',
blue: '#0000ff',
} as const
type Colors = typeof colors;
type Tail<T extends string> = T extends `#${infer HEX}` ? HEX : never;
type ColorType = keyof typeof colors
type HexValidation<T extends keyof Colors> = ReduceToString<ToArray<Tail<Colors[T]>>>
function getColor<C extends keyof Colors>(color: C): HexValidation<C>
function getColor<C extends keyof Colors>(color: C) {
return colors[color]
}
const result = getColor('red') // "ff0000"
Playground
If you try to provide invalid HEX property in colors
object, TS will throw an error.
More explanation you can find in my blog and this answer