【问题标题】:Typescript annoying warning on react props反应道具上的打字稿令人讨厌的警告
【发布时间】:2020-06-16 19:01:45
【问题描述】:

一旦我开始在React 中使用Typescript,我注意到我不喜欢的一件事是需要将每个道具声明给组件。在此之前我们可以使用{...props},但现在我必须在接口中声明每个原生props,例如refplaceholderdefaultValue 等。

interface InputProps {
  customProp: boolean;
  props: any;
}

const Input = ({ customProp, placeholder, ...props }: InputProps) => { 
  //warning 
  return <input type="text" {...props} />;
};

https://codesandbox.io/s/distracted-burnell-vlt3i?file=/src/App.tsx

我想享受只需要在界面中声明非原生道具的旧日子,可能吗?原生 props 已通过 {...props}

【问题讨论】:

  • 嗯.. 是的,这是意料之中的。那么您对此有何疑问?
  • @wentjun 更新了我的问题,见最后一行..

标签: javascript reactjs typescript


【解决方案1】:
import * as React from "react";
import "./styles.css";

interface InputProps {
  customProp: boolean;
  // props: any; // I think it doesn't need to you.
  [key:string]: any;
}

const Input = ({ customProp, placeholder, ...props }: InputProps) => {
  return <input type="text" {...props} />;
};

export default function App() {
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>

      <Input hello="hello" customProp={false} placeholder={"name"} />
    </div>
  );
}

您可以通过[key:string]: any 享受您的旧时光。

但是,我不想推荐使用[key:string]: any

因为typescript 没有任何意义。

而且,在我看来,如果您对typescript 感到压力,您可以改用js

【讨论】:

    【解决方案2】:

    我想享受只需要在界面中声明非原生道具的旧日子,可能吗?

    是的,这是可能的。 Typescript 允许接口从其他接口扩展,因此您可以定义您的接口以包含输入元素所期望的所有内容,以及您的自定义属性:

    export interface ExampleProps extends React.HTMLProps<HTMLInputElement> {
      customProp: boolean;
    }
    
    const Example: React.FC<ExampleProps> = ({ customProp, placeholder, ...rest }) => {
      const { t } = useTranslation();
      return <input type="text" {...rest} />;
    };
    

    有了这个定义,我尝试呈现以下内容是合法的:

    const Thing: FC = () => {
      return <Example placeholder="foo" customProp={true} defaultValue="3" />;
    };
    

    但是打字稿会指出,例如,如果我未能传入自定义道具,或者我是否为占位符传入了一个对象。

    【讨论】:

    • 这就是答案!
    • 顺便说一句,您确实在问题中明确提到了ref,但是这种代码不会转发 refs(无论是在 javascript 中,还是在 typescript 中)。如果这是您需要的东西,请查看React.forwardRef (reactjs.org/docs/forwarding-refs.html)
    【解决方案3】:

    如果您使用 TypeScript,最好的做法是为每个组件严格定义 props 的接口/类型别名。对于您的 Input 组件,正确的接口应该是

    interface InputProps {
      customProp: boolean;
      placeholder: string;
      // add other props below
    }
    

    话虽如此,接口和类型别名可以导出、共享和扩展,这样可以减少重复代码的数量。例如,

    interface OtherInputProps extends InputProps {
      value: string;
    }
    

    当然,您可以执行 [key:string]: any 之类的操作,但这完全违背了使用 TypeScript 的目的,因为您基本上忽略了 TypeScript 的类型检查功能。在这种情况下,t 将不那么冗长,以恢复为 JavaScript。


    编辑:刚刚意识到 OP 正在尝试使用其他道具扩展输入道具。在这种情况下,要使用的正确基类型是 `React.InputHTMLAttributes:

    export interface InputProps extends React.InputHTMLAttributes< HTMLInputElement> {
      customProp: boolean;
    }
    

    type InputProps = React.InputHTMLAttributes<HTMLInputElement> & {
      customProp: boolean;
    }
    

    【讨论】:

    • 每个道具?这有什么意义呢?想象一下我有 ref={ref} placeholder={placeholder} value={value} 并且我必须声明每个本地道具,我假设它可以通过 {...props}
    • 您仍然可以在 TypeScript 中使用{...props},但您必须在目标组件上定义所需的类型。
    • 哦,我想我看错了你的问题。刚刚意识到您要求的是本机 html 输入道具 :)
    猜你喜欢
    • 1970-01-01
    • 2015-01-07
    • 2012-09-02
    • 2010-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-24
    • 1970-01-01
    相关资源
    最近更新 更多