I'm trying to create a standalone type in TypeScript that can be used to represent a single valid HEX color code as a fully type-safe string.
My attempt is below, which falls short due to not actually being a standalone type, which is what I would hope to achieve.
type HexDigit<T extends '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | 'a' | 'b' | 'c' | 'd' | 'e'| 'f' | 'A' | 'B' | 'C' | 'D' | 'E'| 'F'> = T;
type HexColor<T extends string> =
T extends `#${HexDigit<infer D1>}${HexDigit<infer D2>}${HexDigit<infer D3>}${HexDigit<infer D4>}${HexDigit<infer D5>}${HexDigit<infer D5>}`
? T
: (
T extends `#${HexDigit<infer D1>}${HexDigit<infer D2>}${HexDigit<infer D3>}`
? T
: never
);
function hex<T extends string>(s: HexColor<T>): T {
return s;
}
// All valid
hex('#ffffff');
hex('#fff');
hex('#000');
hex('#123456');
hex('#abcdef');
hex('#012def');
hex('#ABCDEF');
Trying to use a type with a generic as a standalone type was bound to fail, so I got stuck at this point.
// Ideal use case - does not compute
const color: HexColor = '#aaa';
const theme: Record<string, HexColor> = {
backgroundColor: '#ff0000',
color: '#0f0',
};
Is this even possible to achieve with TypeScript, and if so, how?