'How can I define a type for a css color in TypeScript?
I have the following example code snippet:
type Color = string;
interface Props {
color: Color;
text: string;
}
function Badge(props: Props) {
return `<div style="color:${props.color}">${props.text}</div>`;
}
var badge = Badge({
color: '#F00',
text: 'Danger'
});
console.log(badge);
I'm trying to get a build error if the color is invalid, like so:
var badge = Badge({
color: 'rgba(100, 100, 100)',
text: 'Danger'
});
Is there a way to define Color
so that it allows only strings matching one of the following patterns?
#FFF
#FFFFFF
rgb(5, 5, 5)
rgba(5, 5, 5, 1)
hsa(5, 5, 5)
I realize that there are colors like red
and white
but that might make this harder to answer if Color
can accept those.
Solution 1:[1]
There was a proposal for a type of string which matches a pattern (regex or something else), but that proposal haven't come to fruition yet.
As a result, what you ask for is unfortunately impossible as of TypeScript 2.2.
Solution 2:[2]
type RGB = `rgb(${number}, ${number}, ${number})`;
type RGBA = `rgba(${number}, ${number}, ${number}, ${number})`;
type HEX = `#${string}`;
type Color = RGB | RGBA | HEX;
`${...}` notation is available on new (^4.1) ts versions.
https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html
Solution 3:[3]
You can't do this yet in a general sense, but you can use constants and string literal types if you have a well defined set of colors:
type Color = "#FFFFFF" | "#FF0000" | "#0000FF";
const WHITE: Color = "#FFFFFF";
const RED: Color = "#FF0000";
const BLUE: Color = "#0000FF";
Obviously, this won't be practical if you want to allow any color, but in reality you probably do want to have re-usable color variables anyway.
In my project I use a script to generate a similar file from my colors.css
file which defines a bunch of CSS properties:
:root {
--primary-red: #ff0000;
--secondary-red: #993333;
/* etc */
}
Which gets converted to:
export const primaryRed: Color = "#ff0000";
export const secondaryRed: Color = "#993333";
// etc
export type Color = "#ff0000" | "#993333" // | etc...
And I'd use it like:
import {primaryRed} from "./Colors.ts";
interface BadgeProps {
color: Color;
text: string;
}
var badge = Badge({
color: primaryRed,
text: 'Danger'
});
Solution 4:[4]
It is theoretically possible with union types, however if you JUST do hex codes, you have well over 16,000,000 possible combinations, and typescript (4.6.3 at least) does not like that idea.
It has been on the backburner for MS for over a year now https://github.com/microsoft/TypeScript/issues/42790
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Oliver Salzburg |
Solution 2 | styfle |
Solution 3 | |
Solution 4 | d3rpp |