Definitelytyped: [react]: defaultProps doesn't work with function component - LibraryManagedAttributes

Created on 17 Oct 2018  路  10Comments  路  Source: DefinitelyTyped/DefinitelyTyped

If you know how to fix the issue, make a pull request instead.

  • [x] I tried using the @types/react package and had problems.
  • [x] I tried using the latest stable version of tsc. https://www.npmjs.com/package/typescript
  • [x] I have a question that is inappropriate for StackOverflow. (Please ask any appropriate questions there).

    • Authors: @ferdaber @johnnyreilly @sandersn @RyanCavanaugh @tkrotoff

Dependencies:

"typescript": "3.1.3"
"@types/react": "16.4.18",
"@types/react-dom": "16.0.9",

Code Sample:

type Props = {
  onClick: (ev: import('react').MouseEvent<HTMLElement>) => void
  children: import('react').ReactChild
} & typeof defaultProps

const defaultProps = { color: 'red' }

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

const handleClick = () => console.log('clicked')
const color = 'red'

export const Example = () => (
  <>
    <Button onClick={handleClick}>Click me</Button>
  </>
)

Current Behaviour:

<Button onClick={handleClick}>Click me</Button> will get compile error

 Property 'color' is missing in type '{ children: string; onClick: () => void; }'.

Following code works with class component as expected:

class Button extends Component<Props> {
  static readonly defaultProps = defaultProps
  render() {
    const { onClick: handleClick, color, children } = this.props

    return (
      <button style={{ color }} onClick={handleClick}>
        {children}
      </button>
    )
  }
}

image

Expected Behaviour:

Make default props work for both class and function components

Most helpful comment

I'll create new issue as this issue was for core functionality described here

All 10 comments

Interesting, I had thought that TS 3.1 allows static properties to be picked up by the typechecker, to prevent exactly this bug?

What's the result of this type check:

function foo() {}
foo.defaultProps = 'abc'

// expecting 'string' here
type DefaultPropsOfFoo = typeof foo extends { defaultProps: infer D } ? D : never

What's the result of this type check:
image

related -> https://github.com/Microsoft/TypeScript/issues/27425

so it's gonna be fixed in 3.2 but before that a whole react types needs to be revamped to be compatible with latest

fixed in 3.2 and react types 16.7.x

@Hotell Is the fix available in 3.2.0-rc? Tried it with @types/react version 16.7.6, and it's still shows missing in type error even though it's in defaultProps of an SFC.

@panjiesw

s the fix available in 3.2.0-rc?

Yup

image

image

make sure your editor consumes proper TS version

image

@Hotell

Do we have to declare the defaultProps like yours? This is how I used to declare it, and TS still complains

2018-11-20-174904_3840x1080_scrot

2018-11-20-174924_3840x1080_scrot

VSCode is properly configured

2018-11-20-174937_3840x1080_scrot

EDIT:

Tried it your way and it works, but I prefer using SFC so I don't have to type children and props completion is also available when declaring defaultProps.

Works for me both ways.

If in doubt restart tsserver or even better execute tsc from terminal ( yarn tsc ):

image

I highly recommend using my pattern:

  • define defaultProps as constant and infer type from it
  • explicitly define children

To learn more check: https://medium.com/@martin_hotell/10-typescript-pro-tips-patterns-with-or-without-react-5799488d6680

but I prefer using SFC

SFC is dead. You should use FunctionalComponent which mitigates usage of generics ( and also introduces unnecessary type "churn" for newbies ) 馃憖

image

Yup just realized that SFC is deprecated. I'll use your pattern if it's the only way to make it works with defaultProps of FunctionComponent, and it also has valid points. Thanks for your article btw!

I put my repro here https://github.com/panjiesw/react-ts-32 in case you want to try it. I still can't get it to work with FunctionComponent<Props> pattern, even running npx tsc gives the same error.

I'll create new issue as this issue was for core functionality described here

Was this page helpful?
0 / 5 - 0 ratings