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

**feat:** improve the ElementAttributes and ReactElementAttributes JSX type helpers. #34

Merged
merged 1 commit into from
Oct 10, 2024

Conversation

trusktr
Copy link
Member

@trusktr trusktr commented Oct 8, 2024

This improves JSX types for Custom Elements in Solid JSX, React JSX, and Preact JSX, especially in React/Preact JSX whereas previously the React/Preact JSX prop types only accepted string values for dash-cased attributes.

If you have a getter/setter property in your element class, you can now define a dummy property prefixed with __set__<name-of-the-setter> to specify the type of the setter, and this will be picked up and lead to improved types in JSX. For example, you can start using like so:

Before:

@element('some-element')
class SomeElement extends Element {
    @attribute get someProp(): number {...}
    @attribute set someProp(n: number | 'foo' | 'bar') {...}
}

declare module 'react' {
    namespace JSX {
        interface IntrinsicElements {
            'some-element': ReactElementAttributes<SomeElement, 'someProp'>
        }
    }
}

and this JSX would have a type error:

return <some-element some-prop={'foo'} /> // Error: string is not assignable to number

After:

@element('some-element')
class SomeElement extends Element {
    @attribute get someProp(): number {...}
    @attribute set someProp(n: this['__set__someProp']) {...}

    /** don't use this property, it is for JSX types. */
    __set__someProp!: number | 'foo' | 'bar'
}

// ... the same React JSX definition as before ...

and now JSX prop types will allow setting the setter types:

return <some-element someProp={'foo'} /> // No error, yay!

Note, the property is camelCase instead of dash-case now.

BREAKING: This may introduce type errors into existing JSX templates, tested with React 19 (not tested with React 18 or below), but it is an inevitable upgrade for the better.
To migrate, there's likely nothing to do in Solid JSX, but in React JSX the selected properties are no longer converted to dash-case, so you'll want to use the original JS property names in React JSX templates. For example this,

return <some-element some-prop={...} />

becomes

return <some-element someProp={...} />

If you have any issues, please reach out here on GitHub or on Discord!

…` JSX type helpers.

This improves JSX types for Custom Elements in Solid JSX, React JSX, and Preact JSX,
especially in React/Preact JSX whereas previously the React/Preact JSX prop types only accepted
string values for dash-cased attributes.

If you have a `get`ter/`set`ter property in your element class, you can
now define a dummy property prefixed with `__set__<name-of-the-setter>`
to specify the type of the `set`ter, and this will be picked up and lead
to improved types in JSX. For example, you can start using like so:

Before:

```js
@element('some-element')
class SomeElement extends Element {
    @Attribute get someProp(): number {...}
    @Attribute set someProp(n: number | 'foo' | 'bar') {...}
}

declare module 'react' {
    namespace JSX {
        interface IntrinsicElements {
            'some-element': ReactElementAttributes<SomeElement, 'someProp'>
        }
    }
}
```

and this JSX would have a type error:

```jsx
return <some-element some-prop={'foo'} /> // Error: string is not assignable to number
```

After:

```js
@element('some-element')
class SomeElement extends Element {
    @Attribute get someProp(): number {...}
    @Attribute set someProp(n: this['__set__someProp']) {...}

    /** don't use this property, it is for JSX types. */
    __set__someProp!: number | 'foo' | 'bar'
}

// ... the same React JSX definition as before ...
```

and now JSX prop types will allow setting the *setter* types:

```jsx
return <some-element someProp={'foo'} /> // No error, yay!
```

Note, the property is camelCase instead of dash-case now.

**BREAKING:** This may introduce type errors into existing JSX templates,
tested with React 19 (not tested with React 18 or below), but it is an
inevitable upgrade for the better.
To migrate, there's likely nothing to do in Solid JSX, but in React JSX
the selected properties are no longer converted to dash-case, so you'll
want to use the original JS property names in React JSX templates. For example this,

```jsx
return <some-element some-prop={...} />
```

becomes

```jsx
return <some-element someProp={...} />
```

If you have any issues, please reach out on GitHub or Discord! https://discord.gg/VmvkFcWrsx

Co-authored-by: bigmistqke <[email protected]>
@trusktr trusktr force-pushed the update-jsx-type-helpers branch from ed72493 to babd555 Compare October 8, 2024 06:51
@trusktr trusktr merged commit e45035c into main Oct 10, 2024
0 of 3 checks passed
@trusktr trusktr deleted the update-jsx-type-helpers branch October 10, 2024 21:56
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.

1 participant