Definitelytyped: [@types/react] PropsWithChildren is incorrect or misleading.

Created on 12 Dec 2019  路  9Comments  路  Source: DefinitelyTyped/DefinitelyTyped

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

  • [x] I tried using the @types/xxxx 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).
  • [x] [Mention](https://github.com/blog/821-mention-somebody-they-re-notified) the authors (see Definitions by: in index.d.ts) so they can respond.

    • Authors: @johnnyreilly @bbenezech @pzavolinsky @digiguru @ericanderson @DovydasNavickas @theruther4d @guilhermehubner @ferdaber @jrakotoharisoa @pascaloliv @hotell @franklixuefei @Jessidhia @saranshkataria @lukyth @eps1lon @zika


I prefer to be explicit with my types, and I noticed something, that all components, at least functional ones that use React.FC or React.FunctionComponent have a generic that unionizes with PropsWithChildren that automatically adds { children?: ReactNode } and I feel that is incorrect or misleading.

Given a component that does not accept or use children that prop should not be present, right? It's not passed by React at all. Example shown in screenshot below. So why is it given as a potential prop default on all component types?

I feel this defeats the purpose of types. TypeScript should technically give an error if you did <Foo>hi</foo> and <Foo /> never used the children prop.

image

Most helpful comment

The maintainers of the library agree with this philosophy, however we have the problem that DT does not follow semver, so removing this is a large breaking change. We were hoping to make this change when React releases another major version, so that we can just piggy back off of the major version change.

All 9 comments

The maintainers of the library agree with this philosophy, however we have the problem that DT does not follow semver, so removing this is a large breaking change. We were hoping to make this change when React releases another major version, so that we can just piggy back off of the major version change.

The maintainers of the library agree with this philosophy, however we have the problem that DT does not follow semver, so removing this is a large breaking change. We were hoping to make this change when React releases another major version, so that we can just piggy back off of the major version change.

Oh good. I had just been ignoring it and using peak intellisense in VSCode to make sure my components don't have a children prop in the event I forget.

No problems working around it for now knowing it'll be fixed.

Awesome, will be glad to see this update on a new major version of React!

Instead of a breaking change, have the maintainers considered adding a VoidFunctionComponent type? It may be defined like this:

interface VoidFunctionComponent<P = {}> {
    (props: P, context?: any): ReactElement<any, any> | null;
    propTypes?: WeakValidationMap<P>;
    contextTypes?: ValidationMap<any>;
    defaultProps?: Partial<P>;
    displayName?: string;
}

Changing the type of FunctionComponent to remove children could break a _ton_ of things, especially libraries that rely on the specific children: React.ReactNode prop type. By removing it completely, the type of children is up to the component authors and there is a risk of breaking compatibility with those libraries.

Introducing a new type avoids this breakage, and can help cement an analogy with HTML element types:

  • VoidFunctionComponent -> void HTML element
  • FunctionComponent -> normal HTML element

P.S. a workaround in the meantime, though a bit ugly, is to take advantage of the type intersection in PropsWithChildren:

interface ComponentProps {
  foo: string;
  children?: never;
}

const MyComponent: FunctionComponent<ComponentProps> = props => (...)

This will throw a type error if you pass children into MyComponent.

@awmottaz are you speaking about libraries that consume types, or libraries that create types? Your reasoning sounds like breakage in libraries that consume types

that is a cool idea, I would want a React.VFC shorthand as well

Remember that this isn't just about function components that don't accept children, but also function components that accept other types than ReactNode as children, which currently have no way of opting out aside from defining their own annotation.

@ferdaber

are you speaking about libraries that consume types, or libraries that create types? Your reasoning sounds like breakage in libraries that consume types

That's correct, I was considering libraries that consume types.

Just my two cents of the approach I have chosen regarding children and props.

https://gist.github.com/FredyC/3aba908bb0894b83dc25cf1a02d1928d

Was this page helpful?
0 / 5 - 0 ratings

Related issues

JWT
svipas picture svipas  路  3Comments

Loghorn picture Loghorn  路  3Comments

fasatrix picture fasatrix  路  3Comments

variousauthors picture variousauthors  路  3Comments

jbreckmckye picture jbreckmckye  路  3Comments