csstype icon indicating copy to clipboard operation
csstype copied to clipboard

How to limit the StandardLonghandProperties[`propertyName`] type to valid strings?

Open bart-krakowski opened this issue 3 years ago • 1 comments

I'd like to make sure the user will be able to provide only a valid strings to a component with this props:

interface ComponentProps {
  width?: StandardLonghandProperties["width"]
}

but it allows to provide any string or number:

<Component width="foo-bar" />

I've noticed that it could work when I remove | (string & {}); from this interface:

  export type Width<TLength = (string & {}) | 0> =
    | Globals
    | TLength <--- this might be string
    | "-moz-fit-content"
    | "-moz-max-content"
    | "-moz-min-content"
    | "-webkit-fit-content"
    | "-webkit-max-content"
    | "auto"
    | "fit-content"
    | "intrinsic"
    | "max-content"
    | "min-content"
    | "min-intrinsic"
    | (string & {}); <---

Now I'm able to pass 0 as a type param to the StandardLonghandProperties interface:

interface ComponentProps {
  width?: StandardLonghandProperties<0>["width"]
}

...

<Component width="foo-bar" /> // this fails
<Component width="auto" /> // this pass
<Component width="10px" /> // this fails

As a solution for the issue with px, rem etc I suggest using Template Literal Types:

    | `${number}${`px`|`em`|`rem`|`vw`|`vh`}`;

bart-krakowski avatar Oct 12 '22 10:10 bart-krakowski

It'd have to be:

type Unit = `${number}${`ch`|`em`|`px`|`rem`|`vh`|`vw`|`%`}`;
type CSSFunction = `${string}(--${string | number})`; // like `var(--some-var)` or `calc(100% - 220px)`

type StandardLonghandPropertiesValue = Unit | CSSFunction;

at least.

Can't think of other edge cases, but this sort of typing is tough... Even CSSFunction could be spoofed wrong.

kylemh avatar Oct 16 '22 20:10 kylemh