Typing defaultProps
defaultProps
You May Not Need As per this tweet, defaultProps will eventually be deprecated. You can check the discussions here:
The consensus is to use object default values.
Function Components:
Class Components:
defaultProps
Typing Type inference improved greatly for defaultProps
in TypeScript 3.0+, although some edge cases are still problematic.
Function Components
For Class components, there are a couple ways to do it(including using the Pick
utility type) but the recommendation is to "reverse" the props definition:
`JSX.LibraryManagedAttributes` nuance for library authors
The above implementations work fine for App creators, but sometimes you want to be able to export GreetProps
so that others can consume it. The problem here is that the way GreetProps
is defined, age
is a required prop when it isn't because of defaultProps
.
The insight to have here is that GreetProps
is the internal contract for your component, not the external, consumer facing contract. You could create a separate type specifically for export, or you could make use of the JSX.LibraryManagedAttributes
utility:
`This will work properly, although hovering over
ApparentGreetPropsmay be a little intimidating. You can reduce this boilerplate with the
ComponentProps` utility detailed below.
Consuming Props of a Component with defaultProps
A component with defaultProps
may seem to have some required props that actually aren't.
Problem Statement
Here's what you want to do:
Solution
Define a utility that applies JSX.LibraryManagedAttributes
:
Misc Discussions and Knowledge
Why does React.FC break defaultProps?
You can check the discussions here:
- https://medium.com/@martin_hotell/10-typescript-pro-tips-patterns-with-or-without-react-5799488d6680
- https://github.com/DefinitelyTyped/DefinitelyTyped/issues/30695
- https://github.com/typescript-cheatsheets/react-typescript-cheatsheet/issues/87
This is just the current state and may be fixed in future.
TypeScript 2.9 and earlier
For TypeScript 2.9 and earlier, there's more than one way to do it, but this is the best advice we've yet seen:
Our former recommendation used the Partial type
feature in TypeScript, which means that the current interface will fulfill a partial version on the wrapped interface. In that way we can extend defaultProps without any changes in the types!
The problem with this approach is it causes complex issues with the type inference working with JSX.LibraryManagedAttributes
. Basically it causes the compiler to think that when creating a JSX expression with that component, that all of its props are optional.