Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
3 tasks done
Hotell opened this issue Oct 17, 2018 · 10 comments
Closed
3 tasks done

Comments

@Hotell
Copy link
Contributor

Hotell commented Oct 17, 2018

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

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

@Hotell Hotell changed the title [react]: defaultProps doesn't work with functions - LibraryManagedAttributes [react]: defaultProps doesn't work with function component - LibraryManagedAttributes Oct 17, 2018
@ferdaber
Copy link
Contributor

ferdaber commented Oct 17, 2018

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

@Hotell
Copy link
Contributor Author

Hotell commented Oct 17, 2018

What's the result of this type check:
image

@Hotell
Copy link
Contributor Author

Hotell commented Oct 25, 2018

related -> microsoft/TypeScript#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

@Hotell
Copy link
Contributor Author

Hotell commented Nov 19, 2018

fixed in 3.2 and react types 16.7.x

@Hotell Hotell closed this as completed Nov 19, 2018
@panjiesw
Copy link

@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.

@Hotell
Copy link
Contributor Author

Hotell commented Nov 20, 2018

@panjiesw

s the fix available in 3.2.0-rc?

Yup

image

image

make sure your editor consumes proper TS version

image

@panjiesw
Copy link

panjiesw commented Nov 20, 2018

@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.

@Hotell
Copy link
Contributor Author

Hotell commented Nov 20, 2018

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

@panjiesw
Copy link

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.

@Hotell
Copy link
Contributor Author

Hotell commented Nov 20, 2018

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants