简体   繁体   中英

Spreading props on a React component with Typescript

New to Typescript + React and I'm trying to spread props on the root node of ListItem . For example, I'd like to allow data-* and aria-* attributes for this component. Below is an example component that represents the issue I'm having.

import { forwardRef, HTMLAttributes } from 'react';

interface ListItemProps extends HTMLAttributes<HTMLElement> {
  disabled?: boolean;
  active?: boolean;
  href?: string;
}

const ListItem = forwardRef<HTMLLIElement, ListItemProps>((props, ref) => {
  const {
    active,
    disabled,
    className,
    style,
    children,
    ...other
  } = props;

  return (
    <li // throws error 
      ref={ref}
      style={style}
      {...other}
    >{children}</li>
  );
});

export default ListItem;

I'm getting this typescript error:

TS2322: Type '{ children: Element; href?: string | undefined; defaultChecked?: boolean | undefined; defaultValue?: string | string[] | undefined; suppressContentEditableWarning?: boolean | undefined; ... 249 more ...; className: string; }' is not assignable to type 'DetailedHTMLProps<LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>'.
  Type '{ children: Element; href?: string | undefined; defaultChecked?: boolean | undefined; defaultValue?: string | string[] | undefined; suppressContentEditableWarning?: boolean | undefined; ... 249 more ...; className: string; }' is not assignable to type 'LiHTMLAttributes<HTMLLIElement>'.
    Types of property 'inputMode' are incompatible.
      Type 'string | undefined' is not assignable to type '"text" | "none" | "tel" | "url" | "email" | "numeric" | "decimal" | "search" | undefined'.
        Type 'string' is not assignable to type '"text" | "none" | "tel" | "url" | "email" | "numeric" | "decimal" | "search" | undefined'.

This is because you have the variable used as inputMode as string (either by annotation or inference).

Fix

Use the annotation React.HTMLAttributes<HTMLLIElement>['inputMode'] (which uses a lookup type ).

Fixed code:

import * as React from 'react';
import { forwardRef, HTMLAttributes } from 'react';

interface ListItemProps extends HTMLAttributes<HTMLElement> {
  disabled?: boolean;
  active?: boolean;
  href?: string;
}

const ListItem = forwardRef<HTMLLIElement, ListItemProps>((props, ref) => {
  const {
    active,
    disabled,
    className,
    style,
    children,
    ...other
  } = props;

  return (
    <li // throws error 
      ref={ref}
      style={style}
      {...other}
    >{children}</li>
  );
});

// Issue with inputMode
let asString = "text";
const error = <ListItem inputMode={asString}/>;

// Fix 
let correctType:React.HTMLAttributes<HTMLLIElement>['inputMode']  = "text";
const ok = <ListItem inputMode={correctType}/>;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM