小编典典

使用 TypeScript 的 React 组件中的默认属性值

all

我不知道如何使用 Typescript 为我的组件设置默认属性值。

这是源代码:

class PageState
{
}

export class PageProps
{
    foo: string = "bar";
}

export class PageComponent extends React.Component<PageProps, PageState>
{
    public render(): JSX.Element
    {
        return (
            <span>Hello, world</span>
        );
    }
}

当我尝试使用这样的组件时:

ReactDOM.render(<PageComponent />, document.getElementById("page"));

我收到一条错误消息,提示foo缺少属性。我想使用默认值。我也尝试static defaultProps = ...在组件内部使用,但我怀疑它没有效果。

src/typescript/main.tsx(8,17): error TS2324: Property 'foo' is missing in type 'IntrinsicAttributes & IntrinsicClassAttributes<PageComponent> & PageProps & { children?: ReactEle...'.

如何使用默认属性值?我公司使用的许多 JS 组件都依赖于它们,不使用它们不是一种选择。


阅读 59

收藏
2022-07-07

共1个答案

小编典典

带有类组件的默认道具

使用static defaultProps是正确的。您还应该为道具和状态使用接口,而不是类。

2018/12/1 更新 :TypeScript
改进了与defaultProps时间相关的类型检查。继续阅读最新和最有用的用法,直至旧用法和问题。

对于 TypeScript 3.0 及更高版本

TypeScript
特别添加了defaultProps对使类型检查按您期望的方式工作的支持。例子:

interface PageProps {
  foo: string;
  bar: string;
}

export class PageComponent extends React.Component<PageProps, {}> {
    public static defaultProps = {
        foo: "default"
    };

    public render(): JSX.Element {
        return (
            <span>Hello, { this.props.foo.toUpperCase() }</span>
        );
    }
}

可以在不传递foo属性的情况下渲染和编译:

<PageComponent bar={ "hello" } />

注意:

  • foo没有标记为可选(即),即使它不是 JSX 属性所必需的 foo?: string标记为可选意味着它可能是undefined,但实际上它永远不会是undefined,因为defaultProps它提供了一个默认值。可以将其想象为类似于如何将函数参数标记为可选或使用默认值,但不能同时使用两者,但两者都意味着调用不需要指定 value。TypeScript 3.0+defaultProps以类似的方式处理,这对 React 用户来说真的很酷!
  • defaultProps没有显式类型注释。编译器推断并使用它的类型来确定需要哪些 JSX 属性。您可以使用defaultProps: Pick<PageProps, "foo">来确保defaultProps匹配PageProps. 此处解释了有关此警告的更多信息。
  • 这需要@types/react版本16.4.11才能正常工作。

对于 TypeScript 2.1 到 3.0

在 TypeScript 3.0 实现编译器支持之前,defaultProps你仍然可以使用它,并且它在运行时与 React 100% 工作,但由于
TypeScript 在检查 JSX 属性时只考虑道具,你必须将具有默认值的道具标记为可选?。例子:

interface PageProps {
    foo?: string;
    bar: number;
}

export class PageComponent extends React.Component<PageProps, {}> {
    public static defaultProps: Partial<PageProps> = {
        foo: "default"
    };

    public render(): JSX.Element {
        return (
            <span>Hello, world</span>
        );
    }
}

注意:

  • 注释是一个好主意defaultPropsPartial<>以便它对你的道具进行类型检查,但你不必为每个必需的属性提供默认值,这没有意义,因为必需的属性永远不需要默认值。
  • 当使用strictNullChecks的值时,this.props.foopossibly undefined需要一个非空断言(即this.props.foo!)或类型保护(即if (this.props.foo) ...)来删除undefined。这很烦人,因为默认的 prop 值意味着它实际上永远不会未定义,但 TS 不理解这个流程。这是 TS 3.0 明确支持defaultProps.

在 TypeScript 2.1 之前

这工作相同,但你没有Partial类型,所以只需省略Partial<>并为所有必需的道具提供默认值(即使这些默认值永远不会被使用)或完全省略显式类型注释。

[带有功能组件](https://facebook.github.io/react/docs/components-and-

props.html#functional-and-class-
components)的默认道具

您也可以defaultProps在函数组件上使用,但您必须将函数键入FunctionComponentStatelessComponent@types/react之前的版本中16.7.2)接口,以便
TypeScript 知道defaultProps函数:

interface PageProps {
  foo?: string;
  bar: number;
}

const PageComponent: FunctionComponent<PageProps> = (props) => {
  return (
    <span>Hello, {props.foo}, {props.bar}</span>
  );
};

PageComponent.defaultProps = {
  foo: "default"
};

请注意,您不必在Partial<PageProps>任何地方使用,因为FunctionComponent.defaultProps已在 TS
2.1+ 中指定为部分。

另一个不错的选择(这是我使用的)是解构您的props参数并直接分配默认值:

const PageComponent: FunctionComponent<PageProps> = ({foo = "default", bar}) => {
  return (
    <span>Hello, {foo}, {bar}</span>
  );
};

那你根本不需要defaultProps!请注意,如果您 确实 在函数组件上提供defaultProps,它将优先于默认参数值,因为 React
将始终显式传递defaultProps值(因此参数永远不会未定义,因此永远不会使用默认参数。)所以你会使用一个或另一个,而不是两者。

2022-07-07