Typescript/React扩展默认功能组件属性时出错

6gpjuf90  于 2023-01-18  发布在  TypeScript
关注(0)|答案(2)|浏览(150)

对于我的死亡,我不能弄清楚这一点,在过去的三个小时,我非常沮丧,所以我提前道歉,如果我听起来很大的侵略性。
我想要的只是能够为我的组件定义一个typescript接口,并让它扩展任何组件使用的默认接口,以避免在我自己的接口中声明每一个该死的默认属性,如classNameonClick等。
我有这个组件:

import React, { useEffect, useRef, FunctionComponent } from 'react'
import './style.scss'

interface ISideProps {
  wideModeEnabled: boolean
  toggleWideMode
  setFocus
}

const AppLayoutSide: FunctionComponent<ISideProps> = (props) => {
  const ref = useRef() as any
  ...
  ...
  etc.
  return <div {...props} />
}

现在这个组件没有错误了,至少typescript没有给予任何错误,但是如果我试图在另一个组件中呈现这个组件,例如:

const otherComponent = () => {
  return (
    <div className='content'>
      <Menu />
      <Main />
      <Side
        className={'whatever'}  //Typescript error happens here
        wideModeEnabled={wideMode}
        toggleWideMode={toggleWideMode}
        setFocus={setSideFocus}
      />
    </div>
  )
}

错误显示:
类型“{类名称:字符串;已启用宽模式:布尔值;切换宽模式:()=〉无效;无法将“setFocus:Dispatch; }”赋给类型“IntrinsicAttributes & ISideProps & {子级?:React节点;}“。
类型“IntrinsicAttributes & ISideProps & { children?:”上不存在属性“className”React节点;}'. ts(2322)
这显然是真的,我没有在ISideProps接口上定义className,但是我想扩展默认的react props该死的!不管我怎么尝试,我似乎都不能让它工作。每个在线指南都建议在组件声明中添加: FunctionalComponent<ISideProps>,我做到了,但是它没有解决任何问题。
帮帮忙,我快疯了。

cuxqih21

cuxqih211#

使用type(个人首选项)

在使用react和typescript多年之后,我更喜欢使用type而不是interface来定义 prop :

// Can use any other html tag instead of "th"
type CustomThProps = JSX.IntrinsicElements["th"] & {
  otherProp: string;
}

const CustomTh = ({ otherProp, children, ...rest }: CustomThProps) => {
  return ( 
    <th {...rest}>{ children } </th>
}

不幸的是,使用JSX.IntrinsicElements只适用于type,而不适用于interface。我最喜欢这种方法的原因是,您可以方便地使用html标记,而不必知道th在JSX中转换为HTMLTableHeaderCellElement

使用interface(更新的答案)

如果你想使用接口,与HTMLAttributes<T>相比,HTMLProps<T>似乎是最可靠和通用的。
例如,当你想为<th>-元素扩展props时,你不能再使用HTMLAttributes<T>,而必须使用ThHTMLAttributes<T>

interface IProps extends React.ThHTMLAttributes<HTMLTableHeaderCellElement>
{
...
}

对于HTMLProps<T>,您可以始终使用相同的签名:

interface IProps extends React.HTMLProps<HTMLTableHeaderCellElement>
{
...
}

使用interface(旧答案)

从react的内置界面扩展你的 prop ,并像这样解构你的 prop :

interface ISideProps extends React.HTMLAttributes<HTMLDivElement>
{
...
}

const AppLayoutSide = (props: ISideProps) => { 
const { wideModeEnabled,  toggleWideMode, setFocus, ...rest } = props;

return (<div {...rest}></div>)
}
yebdmbv4

yebdmbv42#

我想要的只是能够为我的组件定义一个typscript接口,并让它扩展任何组件使用的默认接口
在这种情况下,您可以定义DefaultProps接口,然后使用它来扩展任何组件属性:

interface DefaultProps {
    onClick?: Function;
    className?:string;
}

interface ISideProps extends DefaultProps {
    wideModeEnabled: boolean;
    // ...
}

这需要为自定义组件完成,默认情况下,不期望接收任何属性。
另一方面,像<div><span>这样的内置组件已经定义了对应于其HTML元素的prop,例如<img>,将定义src prop。
为了使用这些预定义的接口,您可以从React模块使用它们,如@oemera所建议的那样。

相关问题