system-ui / theme-ui

Build consistent, themeable React apps based on constraint-based design principles

Home Page:https://theme-ui.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.