Inferred type causes confusion
samueljseay opened this issue · comments
Describe the bug
If you declare a style object and don't explicitly type it as ThemeUICSSObject
then the ThemeUIStyleObject
type is inferred and position: string
is not ok with that type.
To Reproduce
Here's a minimal reproduction
Expected behavior
I would expect the inferred type to be ok with position: string
.
Screenshots
n/a
Additional context
n/a
Hey @samueljseay 👋 Thanks for the issue!
I'm probably going to dissapoint you here, but this is by design.
We can either typecheck position or assume it's always a string and any arbitrary string.
What's happening?
ThemeUIStyleObject type is inferred and position: string is not ok with that type.
What's happening here is that the inferred (just a fancy word for automatic detection) type is { position: string }
, and sx
prop requires an argument of type assignable to ThemeUIStyleObject
.
If you take a look at the error message, you'll notice
Type 'string' is not assignable to type 'StylePropertyValue<Position | undefined>'
TypeScript doesn't know that your position is of type Position = "relative" | "absolute" | ...
because it infers just string
.
I explained the solution in the docs https://theme-ui.com/guides/typescript/#union-types-are-not-inferred-without-explicit-annotation
Can we change this?
If you're okay with position: "relative" (string)
you're also okay with position: "Tyrannosaurus Rex" (string)
.
I imagine there might be a CSS-in-JS library that allows any string, but we can't change our stance, as we're buiding on top of @emotion/react
(TS Playground as proof).
Duplicate of #907
Hey @herrethan. The problem you described in #2166 (comment) is described in this issue.
Would you expect Theme UI to accept any string under position:
and forfeit typechecking here?
Hey @hasparus , I knew I read that somewhere! This discussion is also relevant to the TS evolution on the topic. I definitely prefer keeping it as is, typed as Position
, even if TypeScript can't jump to infer that yet.
I'd rather live with const style: ThemeUICSSObject = { whiteSpace: 'pre-line' }
until it does.