Skip to content

Mimicking JSX attributes behaviour with object types #28960

Closed
@OliverJAsh

Description

@OliverJAsh

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.

Activity

weswigham

weswigham commented on Dec 11, 2018

@weswigham
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}

added a commit that references this issue on May 4, 2021
eps1lon

eps1lon commented on Aug 23, 2021

@eps1lon
Contributor

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

TrevorBurnham commented on Dec 21, 2021

@TrevorBurnham

Possibly related: #47211

RahelSiddiqi

RahelSiddiqi commented on Mar 22, 2022

@RahelSiddiqi

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

OliverJAsh commented on Feb 13, 2023

@OliverJAsh
ContributorAuthor
amitbeck

amitbeck commented on Sep 5, 2024

@amitbeck

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

eps1lon commented on Sep 5, 2024

@eps1lon
Contributor

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @TrevorBurnham@OliverJAsh@weswigham@eps1lon@amitbeck

        Issue actions

          Mimicking JSX attributes behaviour with object types · Issue #28960 · microsoft/TypeScript