用TypeScript强类型函数组件道具的不同方法

80 阅读2分钟

在React中使用TypeScript最有利的部分之一是能够拥有强类型的组件道具。这使得使用该组件的开发者能够快速了解他们可以传递什么,并帮助他们避免犯错。

在这篇文章中,我们将通过几种不同的方法来强类型化组件道具的功能。我们将对以下组件的props进行强类型化:

const TextField = ({
  label,
  text,
  onTextChange
}) => (
  <div>
    <label>{label}</label>
    <input
      type="text"
      value={text}
      onChange={e =>
        onTextChange(e.currentTarget.value)
      }
    />
  </div>
);

内联类型注解

也许最简单的方法是在props 函数参数上使用一个内联类型注释:

const TextField = ({
  label,
  text,
  onTextChange
}: {  label: string;  text: string;  onTextChange: (text: string) => void;}) => ...

当我们的组件中只有几个道具,而且这些道具不需要重复使用时,这是一个不错的方法。

如果组件是一个普通的函数而不是一个箭头函数,也可以使用这种方法:

function TextField({
  label,
  text,
  onTextChange
}: {  label: string,  text: string,  onTextChange: (text: string) => void}) {  ...
}

类型别名

我们可以将道具提取到一个类型别名中:

type Props = {  label: string;  text: string;  onTextChange: (text: string) => void;};const TextField = ({
  label,
  text,
  onTextChange
}: Props) => ...

当至少有几个道具,或者我们想在多个组件中重复使用道具类型时,这种方法很好。

同样,这种方法也可以用于常规函数组件:

function TextField({
  label,
  text,
  onTextChange
}: Props) ...

接口

我们可以使用一个接口来代替类型别名:

interface Props {
  label: string;
  text: string;
  onTextChange: (text: string) => void;
}

现在接口的功能与类型别名非常相似,所以一般来说,使用哪种接口是个人的偏好。

FC 类型

有一个标准的React类型,FC ,我们可以在箭头函数组件上使用。"FC "代表函数组件,它别名一个叫做FunctionComponent 的类型:

const TextField: React.FC<Props> = ({  label,
  text,
  onTextChange
}) => ...

FC 类型被用于分配给箭头函数的变量上。它是一个通用类型,我们将组件的道具类型传入其中。

使用FC 类型有一些可以争论的小好处:

  • FC 在 上提供了一些类型安全,它可以用来为道具提供默认值。然而, 可能会在未来的版本中从 React 中删除。defaultProps defaultProps
  • FC 包括了 道具类型,所以你不需要明确地定义它。然而,可以说,明确地定义它是更好的,这样消费者就可以肯定地知道这是否可用。children

扩展一个标准类型

props类型可以扩展一个标准类型:

interface Props
  extends React.InputHTMLAttributes<    HTMLInputElement  > {  label: string;
  text: string;
  onTextChange: (text: string) => void;
}

在上面的例子中,我们已经为一个input 元素扩展了标准的props类型。这意味着我们的组件现在可以接受诸如maxLengthplaceholder 等道具。

另外,我们也可以使用一个类型别名和交集来达到同样的效果:

type Props = React.InputHTMLAttributes<  HTMLInputElement> & {  label: string;
  text: string;
  onTextChange: (text: string) => void;
};