So I have a react project where the component takes a height prop. That prop is used to determine the css properties for the component (I use the emotion library)
For example,
render() {
const styles = css`
height: ${this.props.height};
`;
return (
<div style={styles}>
...
</div>
);
}
I have a type for height, which is currently
interface Props {
height: number | string;
}
Instead of having a type that checks if the height is a string, I want to create a type that validates the unit of height if it is a string.
For example,
10px
is a valid prop, so no typescript error.
10xp
will throw a typescript error.
Is there a way to create a type that checks that the first part is a number, and the second part is one of these values?
type CssAbsoluteUnit = "cm" | "mm" | "in" | "px" | "pt" | "pc";
type CssRelativeUnit = "em" | "ex" | "ch" | "rem" | "vw" | "vh" | "vmin" | "vmax" | "%";
I'd like to do this in a way that typescript compiler will throw an error, so using just regex to validate on render doesn't really do the job.
Unfortunately, this sounds like something that is determined during runtime after the compiler has done it's job. However, if you know ahead of time, what values that are going to be passed you can create an interface and implement the classes for the types that are going to be passed in.
Something like this:
interface CssUnit {
getValue(): string;
}
class PxUnit implements CssUnit {
private unit: string;
constructor(value: number) {
this.unit = value + "px";
}
getValue(): string {
return this.unit;
}
}
then,
interface Props {
height: CssUnit;
}
All you would have do to is pass in one of your implemented classes.
Hope that helps!
This can be achieved with the Template Literal Type, although there are some limitations around what may incorrectly pass as valid:
type Unit = '%' | 'px' | 'em' | 'vh' | 'vh'
type HeightProp = `${number}${Unit}`
const valid: WidthValue[] = ['10%', '100px', '100em', '100vh', '100vw'] // Valid
const invalid: WidthValue[] = ['10leagues', 'one-hundred-px'] // Error
const falseNegative: WidthValue[] = ['10 px', '0e1px'] // Invalid but passes
This example isn't exhaustive, but the concept could be expanded into covering a wider range of CSS properties and valid values.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With