React Typescript Class Component Default Props Interface

旧时模样 提交于 2021-01-29 20:29:07

问题


I created a simple class component with some props. Since Typescript 3 and above, they state that defaultProps by default will use the same Interface as the component's props itself. reference

In the following code example, you can see I created a component, extending React.PureComponent with a given interface. One prop is called boolean with type boolean.

Then I got the static defaultProps assignment where I made an "accidental" typo where I put a string instead of a boolean.

import React from "react";

export interface ExampleClassProps {
  string: string;
  arrayOfStrings: { test: string };
  boolean: boolean;
}

class ExampleClass extends React.PureComponent<ExampleClassProps> {
  static defaultProps = {
    string: "asd",
    arrayOfStrings: { test: "asd" },
    boolean: "true" //this should throw an error, since I'm assigning a string to type boolean
  };
  render() {
    return <div>{this.props.string}</div>;
  }
}
export default ExampleClass;

From my understanding Typescript should now throw an error saying, type string is not assignable to type boolean, but it doesn't.

I'm on Typescript 3.5.3 and I installed @types/react.

Also, writing a similar component as a functional component does actually work, so I only got the problem with classes:

import React from "react";

export interface ExampleFCProps {
  stringProp?: string;
}

const ExampleFC: React.FC<ExampleFCProps> = ({ stringProp }) => {
  return <div>{stringProp}</div>;
};

ExampleFC.defaultProps = { stringProp: 1 }; //this throws an error, since number is not type string

export default ExampleFC;


回答1:


I don't think that's quite what the documentation you referenced means. It says this:

The default-ed properties are inferred from the defaultProps property type.

I think this means that it looks at the defaultProps property and infers the type from its value: it doesn't look at the type of the props of the component. That makes sense, because if it did assume that defaultProps has the same type as props then you could never supply just a partial set of the props by default: defaultProps would always have to give a value for everything in props.

What the documentation suggests for such a case is this:

Use static defaultProps: Pick<Props, "name">; as an explicit type annotation instead, or do not add a type annotation as done in the example above.

In your example, if you want to supply default values for every prop, and have a it type-checked, explicitly tell the compiler that defaultProps is of type ExampleClassProps:

class ExampleClass extends React.PureComponent<ExampleClassProps> {
    static defaultProps: ExampleClassProps = { // <-- explicitly state the type
        string: "asd",
        arrayOfStrings: { test: "asd" },
        boolean: "true" //this now does not compile, since you're assigning a string to type boolean
    };

By the way, there's an interesting tip about this here: https://medium.com/@martin_hotell/10-typescript-pro-tips-patterns-with-or-without-react-5799488d6680. See the section called "9. Use type inference for defining Component State or DefaultProps".



来源:https://stackoverflow.com/questions/57612132/react-typescript-class-component-default-props-interface

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!