我不知道如何使用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组件都依赖于它们,不使用它们不是一种选择。

最佳答案

带有类组件的默认 Prop

使用static defaultProps是正确的。您还应该使用接口(interface)(而不是类)作为 Prop 和状态。

更新2018/12/1 :随着时间的推移,TypeScript改进了与defaultProps相关的类型检查。继续阅读以获取最新和最佳用法,直至较老的用法和问题。

对于TypeScript 3.0及更高版本

TypeScript专门使用added support for 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未被标记为可选(即foo?: string),尽管它不是JSX属性所必需的。标记为可选将意味着它可以是undefined,但是实际上它永远不会是undefined,因为defaultProps提供了默认值。认为它类似于you can mark a function parameter optional, or with a default value, but not both, yet both mean the call doesn't need to specify a value。 TypeScript 3.0+以类似的方式对待defaultProps,这对于React用户真的很酷!
  • defaultProps没有显式类型注释。推断出它的类型,并由编译器用来确定所需的JSX属性。您可以使用defaultProps: Pick<PageProps, "foo">来确保defaultPropsPageProps的子集匹配。关于此警告的更多信息是explained here
  • 这需要@types/react版本16.4.11才能正常工作。

  • 对于TypeScript 2.1直到3.0

    在TypeScript 3.0实现对defaultProps的编译器支持之前,您仍然可以使用它,并且它在运行时可与React一起使用100%,但是由于TypeScript在检查JSX属性时仅考虑了props,因此您必须将带有默认值的props标记为?。例:
    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>
            );
        }
    }
    

    注意:
  • defaultProps注释Partial<>是个好主意,这样它就可以对您的 Prop 进行类型检查,但是您不必为每个必需的属性提供默认值,这是没有意义的,因为必需的属性永远不需要默认值。
  • 使用strictNullChecks时,this.props.foo的值将为possibly undefined,并且需要非null断言(即this.props.foo!)或类型保护(即if (this.props.foo) ...)才能删除undefined。这很烦人,因为默认的prop值意味着它实际上永远不会被定义,但是TS不能理解这一流程。这是TS 3.0添加了对defaultProps的显式支持的主要原因之一。

  • 在TypeScript 2.1之前

    效果相同,但是您没有Partial类型,因此只需省略Partial<>并为所有必需 Prop 提供默认值(即使永远不会使用这些默认值)或完全省略显式类型注释。

    Functional Components的默认 Prop

    您也可以在函数组件上使用defaultProps,但是必须在FunctionComponent(版本StatelessComponent之前的@types/react中为16.7.2)接口(interface)中键入函数,以便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值(因此,永远不会定义参数,因此永远不会使用默认参数。) d使用一个或另一个,而不是两者都使用。

    关于reactjs - 使用TypeScript在React组件中的默认属性值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37282159/

    10-12 12:40
    查看更多