-
Notifications
You must be signed in to change notification settings - Fork 30.5k
[react] allow weaker prop declarations for nullish properties #31280
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -129,35 +129,26 @@ type ExtractedPartialProps = PropTypes.InferProps<typeof partialPropTypes>; | |
| type ExtractedPropsWithoutAnnotation = PropTypes.InferProps<typeof propTypesWithoutAnnotation>; | ||
| type ExtractedPropsFromOuterPropsWithoutAnnotation = PropTypes.InferProps<typeof outerPropTypesWithoutAnnotation>['props']; | ||
|
|
||
| // $ExpectType: true | ||
| // $ExpectType true | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed a longstanding issue with these DTSLint assertions |
||
| type ExtractPropsMatch = ExtractedProps extends ExtractedPropsWithoutAnnotation ? true : false; | ||
| // $ExpectType: true | ||
| // $ExpectType true | ||
| type ExtractPropsMatch2 = ExtractedPropsWithoutAnnotation extends ExtractedProps ? true : false; | ||
| // $ExpectType: true | ||
| // $ExpectType true | ||
| type ExtractPropsMatch3 = ExtractedProps extends Props ? true : false; | ||
| // $ExpectType: true | ||
| // $ExpectType true | ||
| type ExtractPropsMatch4 = Props extends ExtractedPropsWithoutAnnotation ? true : false; | ||
| // $ExpectType: true | ||
| // $ExpectType true | ||
| type ExtractFromOuterPropsMatch = ExtractedPropsFromOuterProps extends ExtractedPropsFromOuterPropsWithoutAnnotation ? true : false; | ||
| // $ExpectType: true | ||
| // $ExpectType true | ||
| type ExtractFromOuterPropsMatch2 = ExtractedPropsFromOuterPropsWithoutAnnotation extends ExtractedPropsFromOuterProps ? true : false; | ||
| // $ExpectType: true | ||
| // $ExpectType true | ||
| type ExtractFromOuterPropsMatch3 = ExtractedPropsFromOuterProps extends Props ? true : false; | ||
| // $ExpectType: true | ||
| // $ExpectType true | ||
| type ExtractFromOuterPropsMatch4 = Props extends ExtractedPropsFromOuterPropsWithoutAnnotation ? true : false; | ||
|
|
||
| // $ExpectType: false | ||
| // $ExpectType false | ||
| type ExtractPropsMismatch = ExtractedPartialProps extends Props ? true : false; | ||
|
|
||
| // $ExpectType: {} | ||
| type UnmatchedPropKeys = Pick<ExtractedPropsWithoutAnnotation, Extract<{ | ||
| [K in keyof ExtractedPropsWithoutAnnotation]: ExtractedPropsWithoutAnnotation[K] extends ExtractedProps[K] ? never : K | ||
| }[keyof ExtractedPropsWithoutAnnotation], keyof ExtractedPropsWithoutAnnotation>>; | ||
| // $ExpectType: {} | ||
| type UnmatchedPropKeys2 = Pick<ExtractedProps, Extract<{ | ||
| [K in keyof ExtractedProps]: ExtractedProps[K] extends ExtractedPropsWithoutAnnotation[K] ? never : K | ||
| }[keyof ExtractedProps], keyof ExtractedProps>>; | ||
|
|
||
| PropTypes.checkPropTypes({ xs: PropTypes.array }, { xs: [] }, 'location', 'componentName'); | ||
|
|
||
| // This would be the type that JSX sees | ||
|
|
@@ -189,15 +180,15 @@ const componentDefaultProps = { | |
| type DefaultizedProps = Defaultize<PropTypes.InferProps<typeof componentPropTypes>, typeof componentDefaultProps>; | ||
| type UndefaultizedProps = Undefaultize<PropTypes.InferProps<typeof componentPropTypes>, typeof componentDefaultProps>; | ||
|
|
||
| // $ExpectType: true | ||
| // $ExpectType true | ||
| type DefaultizedPropsTest = { | ||
| fi?: (...args: any[]) => any; | ||
| foo?: string | null; | ||
| bar: number; | ||
| baz?: boolean | null; | ||
| bat?: ReactNode; | ||
| } extends DefaultizedProps ? true : false; | ||
| // $ExpectType: true | ||
| // $ExpectType true | ||
| type UndefaultizedPropsTest = { | ||
| fi: (...args: any[]) => any; | ||
| foo?: string | null; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -298,7 +298,7 @@ declare namespace React { | |
| } | ||
|
|
||
| interface ProviderExoticComponent<P> extends ExoticComponent<P> { | ||
| propTypes?: ValidationMap<P>; | ||
| propTypes?: WeakValidationMap<P>; | ||
| } | ||
|
|
||
| type ContextType<C extends Context<any>> = C extends Context<infer T> ? T : never; | ||
|
|
@@ -461,23 +461,23 @@ declare namespace React { | |
|
|
||
| interface FunctionComponent<P = {}> { | ||
| (props: P & { children?: ReactNode }, context?: any): ReactElement<any> | null; | ||
| propTypes?: ValidationMap<P>; | ||
| propTypes?: WeakValidationMap<P>; | ||
| contextTypes?: ValidationMap<any>; | ||
| defaultProps?: Partial<P>; | ||
| displayName?: string; | ||
| } | ||
|
|
||
| interface RefForwardingComponent<T, P = {}> { | ||
| (props: P & { children?: ReactNode }, ref: Ref<T> | null): ReactElement<any> | null; | ||
| propTypes?: ValidationMap<P>; | ||
| propTypes?: WeakValidationMap<P>; | ||
| contextTypes?: ValidationMap<any>; | ||
| defaultProps?: Partial<P>; | ||
| displayName?: string; | ||
| } | ||
|
|
||
| interface ComponentClass<P = {}, S = ComponentState> extends StaticLifecycle<P, S> { | ||
| new (props: P, context?: any): Component<P, S>; | ||
| propTypes?: ValidationMap<P>; | ||
| propTypes?: WeakValidationMap<P>; | ||
| contextType?: Context<any>; | ||
| contextTypes?: ValidationMap<any>; | ||
| childContextTypes?: ValidationMap<any>; | ||
|
|
@@ -2558,6 +2558,14 @@ declare namespace React { | |
|
|
||
| type ValidationMap<T> = PropTypes.ValidationMap<T>; | ||
|
|
||
| type WeakValidationMap<T> = { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The weak validation map will transform any prop declaration that can be type Props = { foo?: string }and have it pass checks for HOCs that require it to be: type Props = { foo?: string | null }Most developers do not realize that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi @ferdaber, after upgrading for almost every component. I've tracked down this bug into these changes. I'm wondering if anyone else is getting this error...I'll try to create a reproducible repo soon. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, the problem was a different issue (cc @cuyl) - I've written the fix here: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thx |
||
| [K in keyof T]?: null extends T[K] | ||
| ? Validator<T[K] | null | undefined> | ||
| : undefined extends T[K] | ||
| ? Validator<T[K] | null | undefined> | ||
| : Validator<T[K]> | ||
| }; | ||
|
|
||
| interface ReactPropTypes { | ||
| any: typeof PropTypes.any; | ||
| array: typeof PropTypes.array; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The original
typeproperty for this was not exactly the same as the one in the React type definitions, causing issues with thePropTypes.elementvalidator, which this fixes.