Here's an example that works fine with versions _prior_ to 16.4.8
MyComponent.tsx
import * as React from "react";
import * as PropsTypes from "prop-types";
interface IProps {
hello?: string;
world?: boolean;
}
export const MyComponent: React.SFC<IProps> = props => <div>Hello World!</div>;
MyComponent.propTypes = {
hello: PropsTypes.string,
world: PropsTypes.bool
};
I'm not 100% sure where exactly the issue is coming from but downgrading to 16.4.7 makes everything work.
With 16.4.8 I get this error:
[ts]
Type '{ hello: Requireable<string>; world: Requireable<boolean>; }' is not assignable to type 'ValidationMap<IProps> | undefined'.
Type '{ hello: Requireable<string>; world: Requireable<boolean>; }' is not assignable to type 'ValidationMap<IProps>'.
Types of property 'hello' are incompatible.
Type 'Requireable<string>' is not assignable to type 'Validator<string | undefined>'.
Types of property '[nominalTypeHack]' are incompatible.
Type 'string | null | undefined' is not assignable to type 'string | undefined'.
Type 'null' is not assignable to type 'string | undefined'.
Adding .isRequired
to all props makes the error go away, but... why?
MyComponent.propTypes = {
hello: PropsTypes.string.isRequired,
world: PropsTypes.bool.isRequired
};
No updates?
This "improvement" breaks tens of projects with tons of code. I'm removing prop-types everywhere I can (since Typescript interfaces are used) but this issue is still a real pain in the rear compartment.
For now my solution is to manually install @types/[email protected] but then again, it has to be done for every single project individually.
It's one of those cases when a non-breaking release (16.4.x) actually breaks everything (I may be wrongfully assuming you follow semver) 馃槥
BTW, it's not possible to remove usage of prop-types
, if context is used.
Also locking @types/react
to 16.4.7
I'll second the 馃槺 at this breaking a ton of existing projects in a minor version update.
I had to switch to a newer version of React typings for the better defaultProps
handling, but this issue is extremely frustrating.
Using @ts-ignore
is not a solution
I think this caused it: #26813.
@Shakahs are you sure that's it? I think it's about different issue, and it was reverted: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/26946
@ipanasenko I see, you are right, my apologies. I skimmed the PR and it seemed to fit.
Hoping for a resolution to this, or at least a migration path. I too have pinned to 16.4.7 for now.
I've had to lock to 16.4.7 everywhere also. This really needs to be resolved, or the changes in x.8 needs to be reverted.
I was looking into incrementally adding types via TSDoc yesterday and spent most of the day hitting this wall repeatedly. I eventually gave up and still have absolutely no idea how to do this. Is there any sort of documentation for these changes? All I can say is: this is not adoption-friendly. At all.
This is still broken at 16.4.18. Has anyone narrowed down the issue?
@westandy-dcp This was the closest fix: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/29887
But a recent change on master in regards to JSX has broken everything React related. So we're in a shitty limbo state now.
@milesj Any update on the status of React related PRs?
Unfortunately I haven't followed the limbo state closely, though if there is something I can do to help this along, please let me know. With the release of TS 3.2, does that change our status?
@evans All of the @types package using React need to be updated to 3.2. Not sure on the progress of this.
@ferdaber continuing our conversation from #31133, can you give an example of what the nominalTypeHack
accomplishes? I.e. either some code that only compiles with it or some bad code that only doesn't compile with it? (Did that make sense? 馃槃)
The nominalTypeHack
property of a validator is a way of branding a specific prop type validator, as the validator function itself has no inferrable property (even in its call signature) that signifies which type it actually checks for.
That is, without looking at its source code, there is no way to tell that PropTypes.bool
and PropTypes.string
check for different things, so it's a "hack" in the sense that this property does not exist in the actual function object at runtime.
The inference for assignable attributes are done via JSX.LibraryManagedAttributes
, which in a nutshell uses prop types to be able to infer the types of the props a component can receive via its propTypes
static property.
The propTypes
static property is itself a ValidationMap
or rather can be typed as such, and in InferProps
it uses conditional types to infer the "associated type" of a validator via its nominalTypeHack
property.
Requireable
s, by the prop-types package source code, allow for both null
and undefined
to be passed in without causing the prop type warning. More precisely, anything without .isRequired
allows for both null
and undefined
. This is the reason why TS will give the error for props that accept string | undefined
but have its prop type be PropTypes.string
, for example, because it does not actually reflect the true runtime behavior of the prop types checker.
I just had an idea: if someone is willing to check and run the proper tests, we may be able to solve this issue by changing the static propTypes
property of ComponentClass
and FunctionComponent
such that it will create a ValidationMap
of its props that transform nullable and undefined-able props into both, so that it satisfies the DX of developers not having to deal with writing their props as precisely, but also satisfies the type checking of the compiler.
I'm happy to work on this with a little more guidance on how to make sure I'm not breaking the existing type inferences. I can find lots of edits to @types/prop-types that make the red squigglies disappear, but I'm sure they make some things overly permissive.
The change would not be to @types/prop-types
but rather to @types/react
instead, where the canon FunctionComponent
and ComponentClass
types are defined, we need to make the allowable propTypes
property more loose than just ValidationMap<P>
, something like LooseValidationMap<P>
where it widens nullable or undefined-able types to both.
This should be fixed by #31280
Is this supposed to be resolved? I'm still getting this issue even though I can see the PR above reflected in my types
@emilio-martinez This hasn't been an issue for a while now. Be sure your react and all related @types
are at the latest version.
Most helpful comment
No updates?
This "improvement" breaks tens of projects with tons of code. I'm removing prop-types everywhere I can (since Typescript interfaces are used) but this issue is still a real pain in the rear compartment.
For now my solution is to manually install @types/[email protected] but then again, it has to be done for every single project individually.
It's one of those cases when a non-breaking release (16.4.x) actually breaks everything (I may be wrongfully assuming you follow semver) 馃槥