Reputation: 1626
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;
Upvotes: 1
Views: 5731
Reputation: 7026
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".
Upvotes: 2