mirror of
https://github.com/gosticks/DefinitelyTyped.git
synced 2026-10-06 07:47:04 +00:00
[react] better prop typing for JS users (#32182)
* better prop resolutions * lint rules
This commit is contained in:
committed by
John Reilly
parent
7b2a31abb1
commit
a6fd2ee6ac
Vendored
+19
-4
@@ -491,6 +491,10 @@ declare namespace React {
|
||||
getDefaultProps?(): P;
|
||||
}
|
||||
|
||||
type JSXElementConstructor<P> =
|
||||
| ((props: P) => ReactElement<any> | null)
|
||||
| (new (props: P) => Component<P, any>);
|
||||
|
||||
/**
|
||||
* We use an intersection type to infer multiple type parameters from
|
||||
* a single argument, which is useful for many top-level API defs.
|
||||
@@ -719,8 +723,8 @@ declare namespace React {
|
||||
* NOTE: prefer ComponentPropsWithRef, if the ref is forwarded,
|
||||
* or ComponentPropsWithoutRef when refs are not supported.
|
||||
*/
|
||||
type ComponentProps<T extends ReactType> =
|
||||
T extends ComponentType<infer P>
|
||||
type ComponentProps<T extends keyof JSX.IntrinsicElements | JSXElementConstructor<any>> =
|
||||
T extends JSXElementConstructor<infer P>
|
||||
? P
|
||||
: T extends keyof JSX.IntrinsicElements
|
||||
? JSX.IntrinsicElements[T]
|
||||
@@ -2629,9 +2633,20 @@ declare namespace React {
|
||||
}
|
||||
}
|
||||
|
||||
// Declared props take priority over inferred props
|
||||
// naked 'any' type in a conditional type will short circuit and union both the then/else branches
|
||||
// so boolean is only resolved for T = any
|
||||
type IsExactlyAny<T> = boolean extends (T extends never ? true : false) ? true : false;
|
||||
|
||||
// Try to resolve ill-defined props like for JS users: props can be any, or sometimes objects with properties of type any
|
||||
// If props is type any, use propTypes definitions, otherwise for each `any` property of props, use the propTypes type
|
||||
// If declared props have indexed properties, ignore inferred props entirely as keyof gets widened
|
||||
type MergePropTypes<P, T> = P & Pick<T, Exclude<keyof T, keyof P>>;
|
||||
type MergePropTypes<P, T> = IsExactlyAny<P> extends true ? T : ({
|
||||
[K in keyof P]: IsExactlyAny<P[K]> extends true
|
||||
? K extends keyof T
|
||||
? T[K]
|
||||
: P[K]
|
||||
: P[K]
|
||||
} & Pick<T, Exclude<keyof T, keyof P>>);
|
||||
|
||||
// Any prop that has a default prop becomes optional, but its type is unchanged
|
||||
// Undeclared default props are augmented into the resulting allowable attributes
|
||||
|
||||
@@ -222,3 +222,30 @@ interface LeaveMeAloneDtslint { foo: string; }
|
||||
// // $ExpectError the type of ForwardRef.defaultProps stays Partial<P> anyway even if assigned
|
||||
// <ForwardRef str='abc' />
|
||||
// ];
|
||||
|
||||
// const weakComponentPropTypes = {
|
||||
// foo: PropTypes.string,
|
||||
// bar: PropTypes.bool.isRequired
|
||||
// };
|
||||
// interface WeakComponentProps1 {
|
||||
// foo: any;
|
||||
// bar: number;
|
||||
// }
|
||||
// interface WeakComponentProps2 {
|
||||
// foo: string;
|
||||
// bar: any;
|
||||
// }
|
||||
|
||||
// // $ExpectType true
|
||||
// type weakComponentTest1 = JSX.LibraryManagedAttributes<{ propTypes: typeof weakComponentPropTypes }, any> extends {
|
||||
// foo?: string | null
|
||||
// bar: boolean
|
||||
// } ? true : false;
|
||||
// type weakComponentTest2 = JSX.LibraryManagedAttributes<{ propTypes: typeof weakComponentPropTypes }, WeakComponentProps1> extends {
|
||||
// foo?: string | null
|
||||
// bar: number
|
||||
// } ? true : false;
|
||||
// type weakComponentTest3 = JSX.LibraryManagedAttributes<{ propTypes: typeof weakComponentPropTypes }, WeakComponentProps2> extends {
|
||||
// foo: string
|
||||
// bar: boolean
|
||||
// } ? true : false;
|
||||
|
||||
Reference in New Issue
Block a user