Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support signal values for html + svg attributes #3747

Merged
merged 1 commit into from
Sep 27, 2022

Conversation

marvinhagemeister
Copy link
Member

@marvinhagemeister marvinhagemeister commented Sep 26, 2022

This PR updates our JSX type definitions to support passing signals as attributes. In a perfect world we'd be able to do that from @preact/signals, but due to the various declaration merging rules and other factors, this would lead to ambiguity and ordering issues. See: microsoft/TypeScript#50808

Whilst we could nudge users to copy & paste a type definition file into their own project, this would be less than ideal for newcomers or users who solely use JavaScript. So after a bit of back and forth and a bit chatter with @developit, we both felt that enhancing the types here is the most DX friendly way for our users.

Looking at the changes you might be curios why I went the verbose way of adding the signals type for every single property value instead of relying on generics or clever intersection types. To be honest: This was the only way TypeScript would pick the Signals type up. Whenever I tried any other approach, TS would drop the whole interface resolution completely. This makes me suspicious of them having special behavior for JSX types or something. Not sure. Either way I think this isn't too bad and workable. The DX improvement for end users is definitely there and imo outweighs a slight annoyance on our part.

Fixes preactjs/signals#106

Comment on lines +428 to +435
export type CompositionEventHandler<Target extends EventTarget> =
EventHandler<TargetedCompositionEvent<Target>>;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prettier gonna prettier!

@marvinhagemeister marvinhagemeister force-pushed the signals-type branch 2 times, most recently from 41fb88f to 42322ce Compare September 26, 2022 19:33
@coveralls
Copy link

coveralls commented Sep 26, 2022

Coverage Status

Coverage remained the same at 99.527% when pulling eeb5d6c on signals-type into 32163d0 on master.

Copy link
Member

@rschristian rschristian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My knowledge of (and willingness to appease) TS beyond basic types is non-existant so I cannot speak for whether there are possible alternatives, but this is working nicely and is super easy to extend in the future so looks great to me!

The behavior to resolve these types seems different from the standard
behavior from TypeScript. The more elegant way of using generics or
clever intersection types doesn't work. The only thing TS seems to
pick up is enhancing every property by hand.
@marvinhagemeister
Copy link
Member Author

FWIW: I found a way with generics that requires less typing on our part, but it's worse compared to the changes in the PR because TS doesn't unwrap the type in IDE hints.

With the changes in this PR for the checked attribute TS displays: checked?: boolean | SignalLike<boolean> | undefined.

With some generic voodoo, it would display: checked?: Attr<boolean> | undefined instead, which kinda masks that you can pass a signal. Personally, I still prefer the way this PR displays it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Preact's TS definitions don't allow signals to be used in the "value" prop of an <input />
4 participants