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

Mimicking JSX attributes behaviour with object types #28960

Closed
5 tasks done
OliverJAsh opened this issue Dec 11, 2018 · 7 comments
Closed
5 tasks done

Mimicking JSX attributes behaviour with object types #28960

OliverJAsh opened this issue Dec 11, 2018 · 7 comments
Labels
feature-request A request for a new feature In Discussion Not yet reached consensus Suggestion An idea for TypeScript

Comments

@OliverJAsh
Copy link
Contributor

Search Terms

jsx object invalid data attribute nested component react

Suggestion

We have this behaviour for JSX:

Note: If an attribute name is not a valid JS identifier (like a data-* attribute), it is not considered to be an error if it is not found in the element attributes type.

https://www.typescriptlang.org/docs/handbook/jsx.html#attribute-type-checking

import React, { FC } from 'react';

const MyComponent: FC<{ myProp: string }> = props => null;
<MyComponent myProp="foo" data-test="foo" />;

I want this same behaviour but for object types. This is necessary for times when we want to pass some props as a nested object (for whatever reason). Currently this errors:

const MyComponent2: FC<{ props: { myProp: string } }> = props => null;
<MyComponent2 props={{ myProp: 'foo', 'data-test': 'foo' }} />;

As far as I'm aware, there's currently no way to extend the above props type to allow for this behaviour.

Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.
@weswigham
Copy link
Member

You want a combination of #6579 (#21044) and #26797. Today, the logic is hardcoded into how we check jsx literals, but with those you could define, eg, type Props<P> = P & {[index: /^data-/]: unknown}

@eps1lon
Copy link
Contributor

eps1lon commented Aug 23, 2021

It seems like this can be solved in TypeScript 4.4 with template literal types as object keys:

import * as React from 'react';

type DataAttributeKey = `data-${string}`;

interface HTMLAttributes extends React.HTMLAttributes<any> {
    [dataAttribute: DataAttributeKey]: any;
}

function Component(props: { host: HTMLAttributes }) {
    return <div {...props.host} />
}

<Component host={{
    'data-testid': 'component',
    'role': 'generic',
    // @ts-expect-error
    shouldError: 1
}} />

Playground Link

@TrevorBurnham
Copy link

Possibly related: #47211

@RahelSiddiqi
Copy link

in vue3 typescript I am having some property does not exist in the HtmlElement error. please help me to solve this issue.

(property) dataButtons: string

(property) data-buttons: string

Type '{ class: string; dataButtons: string; "data-buttons": string; }' is not assignable to type 'HTMLAttributes'.

Property 'dataButtons' does not exist on type 'HTMLAttributes'.ts(2322)

@OliverJAsh
Copy link
Contributor Author

#28960 (comment)

@amitbeck
Copy link

amitbeck commented Sep 5, 2024

Together with module augmentation it can be defined once in a global type definitions module, e.g. src/types/react.d.ts:

import 'react';

declare module 'react' {
  export interface HTMLAttributes<T> {
    [dataAttribute: `data-${string}`]: any;
  }
}

Not sure why this isn't supported in @types/react already

@eps1lon
Copy link
Contributor

eps1lon commented Sep 5, 2024

Nobody proposed the change yet. It may not be trivial to do since adding properties may break existing typechecking. Somebody just needs to own this change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature-request A request for a new feature In Discussion Not yet reached consensus Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

6 participants