SolvedDefinitelyTyped [react]: defaultProps doesn't work when FunctionalComponent<P> is used


Dependencies:

"typescript": "3.2.0-rc"
"@types/react": "16.7.6",
"@types/react-dom": "16.0.9",

As stated by @Kovensky

https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react/test/managedAttributes.tsx#L167-L175

defaultProps doesn't properly apply on JSX tag when function component is defined via FunctionalComponent

Code:

import React, { FunctionComponent } from 'react'

type Props = {
  onClick: (ev: import('react').MouseEvent<HTMLElement>) => void
  children: import('react').ReactChild
  color: 'red' | 'green'
}

const Button: FunctionComponent<Props> = ({ onClick: handleClick, color, children }) => (
  <button style={{ color }} onClick={handleClick}>
    {children}
  </button>
)
Button.defaultProps = {
  color: 'red'
}

const Test = () => (
  <>
     /* $ExpectError */
    <Button onClick={() => console.log('clicked')}>Click me</Button>
  </>
)

Related:
#29816
microsoft/TypeScript#27425

15 Answers

โœ”๏ธAccepted Answer

from my experience, I stopped to use FunctionComponent definition ( former SFC ) long time ago. Instead, following pattern covers everything that user needs to define a function component with default props:

type Props = { age: number } & typeof defaultProps;
const defaultProps = {
  who: 'Johny Five',
};

const Greet = (props: Props) => {
  /*...*/
};
  • It covers aforementioned issue (your default props wont be checked until the component is used - with this pattern they are checked as you worked with them within component implementation)
  • It allows generic component definition
  • enforces to explicitly define children
  • idiomatic TS/JS (annotating just arguments as normal function - easier for newcomers)

more info in my post https://medium.com/@martin_hotell/10-typescript-pro-tips-patterns-with-or-without-react-5799488d6680 ( points 8. and 9. )

FunctionalComponent should be used only as annotation for HoC if needed.

Fix suggestion:

We can transform FunctionComponent, with addition of 2nd generic argument, which would define static props that are present:

interface FunctionComponentStatics<P = {}> {
  propTypes: React.ValidationMap<P>;
  contextTypes: React.ValidationMap<any>;
  defaultProps: Partial<P>;
  displayName: string;
}

type FixFunctionComponent<
  P extends object = {},
  StaticKeys extends keyof FunctionComponentStatics<P> = never
> = {
  (
    props: P & { children?: React.ReactNode },
    context?: any
  ): React.ReactElement<any> | null;
} & { [K in StaticKeys]: FunctionComponentStatics<P>[K] };

// usage:

type Props = {
  onClick: (ev: import('react').MouseEvent<HTMLElement>) => void;
  children: import('react').ReactChild;
  color: 'red' | 'green';
};

const Button: FixFunctionComponent<Props, 'defaultProps'> = ({
  onClick: handleClick,
  color,
  children,
}) => (
  <button style={{ color }} onClick={handleClick}>
    {children}
  </button>
);

// if this would be missing we would get compile error
// also intellisense and excess property checks works
Button.defaultProps = {
  color: 'red',
};

const Test = () => (
  <>
    /* No Errors ๐Ÿ‘Œ, color is optional */
    <Button onClick={handleClick}>Click me</Button>
  </>
)

WDYT ? IF agreed I'll send an PR

thanks !

Related Issues:

310
DefinitelyTyped [@types/react] RefObject.current should no longer be readonly
It's not It'a intentionally left readonly to ensure correct usage even if it's not frozen ...
165
DefinitelyTyped node_modules/@types/react-native/globals.d.ts (36,15): Duplicate identifier 'FormData'.
Fixed by set compilerOptions.types manually If you know how to fix the issue make a pull request ins...
153
DefinitelyTyped @types/core-js breaks build in version 0.9.37
By adding to my compilerOptions in tsconfig.json solved this issue for me thanks @andy-ms ...
139
DefinitelyTyped [@types/webpack] 'devServer' does not exist in type 'Configuration'
I had better results after explicitly merging the types: I tried using the @types/webpack package an...
124
DefinitelyTyped Cannot find module 'csstype'
Try compilerOptions.moduleResolution: node (Edit by Orta: If you are seeing this inside DefinitelyTy...
103
DefinitelyTyped error TS2304: Cannot find name 'Set'. 815 allowedNodeEnvironmentFlags: Set<string>;
Same here with target and lib as es6 I've managed to fix this by installing @types/node@12.7.4. ...
99
DefinitelyTyped @types/nodemailer 6.2.0 & Typescript 3.5.1 Failure
@ruipaulo ah in your example port is a string and this is incorrect because it have to be number Rep...
96
DefinitelyTyped [@types/react] cannot setState with dynamic key name type-safe
This is a limitation of the compiler itself inferred types via computed property keys do not support...
95
DefinitelyTyped Implementing defaultProps with ts 2.0 strict null checks
If anyone has a good solution for types and defaultProps I'm all ears We currently do this: ...
85
DefinitelyTyped [@types/koa-router] incompatible type with koa
koa provides us with multiple types for ctx If you know how to fix the issue make a pull request ins...
72
DefinitelyTyped Error: Interface 'Response<ResBody>' incorrectly extends interface 'Response'
I added skipLibCheck: true in tsconfig.json so it worked for me. When I compile from typescript I ge...
71
DefinitelyTyped [@type/react] Generic Props lost with React memo
Unless you need all the baggage maybe just override the typings locally: For some reason React.memo ...
59
DefinitelyTyped TS2339: Property 'user' does not exist on type 'Request<ParamsDictionary, any, any, ParsedQs>'
Man I solved try using --files after ts-node script: ts-node-dev --files When trying to extend the R...
58
DefinitelyTyped react-redux's connect cannot be used as a decorator: type "is not assignable to type 'void'"
To use @connectdirectly (so without introducing custom decorators) I use the following workaround: B...
57
DefinitelyTyped [@types/express] Latest types throw Property 'headers', 'body', 'query' does not exist on type 'Request<any>'
I solved this issue with yarn by doing: Have nice day! If you know how to fix the issue make a pull ...
56
DefinitelyTyped Lodash All declarations of 'WeakMap' must have identical type parameters.
IMO the best workaround is to skipLibCheck: true Once fixed you can remove it. ...
55
DefinitelyTyped [@types/react-router] Type restriction for RouteProps.component creates error
The component is required to be able to receive RouteComponentProps Change your extends React.Compon...
51
DefinitelyTyped Invalid 'reference' directive syntax
Getting the same exception I want to make PR to types-2.0 branch which change commander definitions ...
47
DefinitelyTyped Aphrodite: incompatible with @types/react 15.6.0?
Adding React to the paths object in my tsconfig.json file solved the issue for me for now: ...
41
DefinitelyTyped [lodash] Type 'T' does not satisfy the constraint 'object'.
Ok so your third party probably needs to update their dependency If you know how to fix the issue ma...
40
DefinitelyTyped @types/node observable declaration conflicts with rxjs
If anyone needs an immediate fix downgrading @types/node to 10.1.2 should work (this was the last re...
40
DefinitelyTyped [@types/styled-components] Generics in functional components (and best practise for generics in general)
The generic argument for the wrapped component can be passed like <StyledFoo<FC<Props<Bar>>> .. /> t...
39
DefinitelyTyped Promise<String>.toEqual does not accept string parameter. Requires also Promise.
Until this is fixed there are several workarounds: Fix the version of the typings to 2.5.45 This wil...
34
DefinitelyTyped Babel Plugin Relay Macro TypeScript
For me had to declare the default export: Hoping this will help TypeScript developers. ...
32
DefinitelyTyped [@types/next] withRouter in TypeScript
The just-keep-quiet option: I tried using the @types/next package and had problems I tried using the...
31
DefinitelyTyped @types/jquery giving breaking solution while Gulp build
Also getting an error after upgrading to the latest jquery typings: Reverting to @types/jquery: 2.0....
31
DefinitelyTyped @types/react Make it possible to render a string from a functional component
A workaround is to return a fragment return <>0</> I tried using the @types/react package and had pr...
30
DefinitelyTyped Duplicate identifier with @types/node 10.0
I will be able to look at this tonight. If you know how to fix the issue make a pull request instead...
29
DefinitelyTyped Subsequent property declarations must have the same type...
@allada I was able to reproduce with your pinned versions using yarn (are you using yarn?) - here's ...
27
DefinitelyTyped bluebird 3.0: how to use it as overload for global Promise?
Hi guys @types/bluebird-global is now available Hey everyone! I am using bluebird as a replacement f...
27
DefinitelyTyped [@types/react-router-dom]: withRouter HoC produces compile error: "Property 'match' is missing in type '{}'."
Same issue here: Got: Can be fixed with: Bug with withRouter declaration it can't extract real props...
27
DefinitelyTyped Enzyme instance() method should be able to carry type of wrapped class
that is unnecessary boilerplate @mohsen1 all you need to do from now on is in demonstrated in test h...
27
DefinitelyTyped v14.6.3 has error in node_modules/@types/node/index.d.ts(20,1): error TS1084: Invalid 'reference' directive syntax.
This was the same issue for us and we fixed it by using a fixed version (14.6.2) of @types/node in o...
26
DefinitelyTyped Problem defining interfaces for return document with mongoose
@maicss Can you initialize your mongoose model like this? Can you let me know if that works? ...
26
DefinitelyTyped [styled-components] v4 doesn't support React Native
Fixed now that @types/styled-components@4.1.9 is published! This issue should be closable as the typ...
25
DefinitelyTyped Property 'from' does not exist on type '{}'
If you want to get around this in not a type safe way and only if you are sure you are getting the v...
25
DefinitelyTyped [@types/express]-Type 'P' is not assignable to type 'ParamsArray'
For NPM users to update your dependency on @types/express-serve-static-core without just blowing awa...
25
DefinitelyTyped Incorrect typings for session object
@wenhx here is how I did it First I edited tsconfig.json to include custom defined types ...
24
DefinitelyTyped @types/ramda - Typings do not work for pipe function using R.filter
This is also a big problem for us I tried using the @types/ramda package and had problems I tried us...
24
DefinitelyTyped Cannot find namespace 'moment'
Hi everybody Iam new in using Typescript and angular ...
23
DefinitelyTyped Problem defining interfaces for subdocuments with mongoose
@camilleblanc Here are some alternatives you can try: Cast to any Use mongoose.Types.Array instead o...
22
DefinitelyTyped Error: node_modules/@types/jasmine/index.d.ts(138,47): error TS1005: ';' expected.
As a side note upgrading these types to require TS 2.8+ is not a minor release If you know how to fi...
21
DefinitelyTyped redux-form Field fails compile with type error if custom props on custom component are used
@LKay this typecast is almost alien: I doubt anybody installing this typings will be able to use it ...
21
DefinitelyTyped [@types/react-native]
Remove dom from lib in the tsconfig I just install the latest updates and I got a bunch of errors ...
21
DefinitelyTyped [@types/react-redux] 'hoist-non-react-statics' has no exported member 'NonReactStatics'
I could be wrong but I think the problem is maybe more simple should be downgrading to @types/react-...
20
DefinitelyTyped global declaration of Express.Request.user collides between @types/express-jwt and @types/passport
How to type request.user now: I tried using the @types/express-jwt & @types/passport package togethe...
20
DefinitelyTyped [styled-components] Cannot use forwardRef with styled component
At the moment I didn't come up with a solution yet It looked harder than I expected ...
20
DefinitelyTyped [@types/react] useEffect(async () => ...) does not account for async
Instead of this try this: I had the same issue and it helped. If you know how to fix the issue make ...
19
DefinitelyTyped Is there a typing for package.json?
A type definition for package.json is available in type-fest If you know how to fix the issue make a...