Fix optionality of inferred props

This commit is contained in:
Matt Tingen
2019-04-01 22:15:31 -04:00
parent 0ac2719531
commit ecc3fd0ff3
2 changed files with 32 additions and 7 deletions
+9 -7
View File
@@ -2732,16 +2732,18 @@ declare namespace React {
// so boolean is only resolved for T = any
type IsExactlyAny<T> = boolean extends (T extends never ? true : false) ? true : false;
// Pick properties for which the value is `any`
type PickAny<T> = Pick<T, { [K in keyof T]: IsExactlyAny<T[K]> extends true ? K : never }[keyof T]>;
// 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> = 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>>);
type MergePropTypes<P, T> = IsExactlyAny<P> extends true ? T : string extends keyof P ? P : (
// From declared props, pick properties which are either not `any` or are missing on `propTypes`.
& Pick<P, Exclude<keyof P, keyof PickAny<P>> | Exclude<keyof P, keyof T>>
// From inferred props, pick all properties except those which are not `any` on `Props`
& Pick<T, Exclude<keyof T, Exclude<keyof P, keyof PickAny<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
+23
View File
@@ -235,17 +235,40 @@ interface LeaveMeAloneDtslint { foo: string; }
// foo: string;
// bar: any;
// }
// interface WeakComponentProps3 {
// foo: any;
// bar: any;
// }
// // $ExpectType true
// type weakComponentTest1 = JSX.LibraryManagedAttributes<{ propTypes: typeof weakComponentPropTypes }, any> extends {
// foo?: string | null
// bar: boolean
// } ? true : false;
// // $ExpectType true
// type weakComponentTest2 = JSX.LibraryManagedAttributes<{ propTypes: typeof weakComponentPropTypes }, WeakComponentProps1> extends {
// foo?: string | null
// bar: number
// } ? true : false;
// // $ExpectType true
// type weakComponentTest3 = JSX.LibraryManagedAttributes<{ propTypes: typeof weakComponentPropTypes }, WeakComponentProps2> extends {
// foo: string
// bar: boolean
// } ? true : false;
// // $ExpectError
// const weakComponentOptionalityTest1: JSX.LibraryManagedAttributes<{ propTypes: typeof weakComponentPropTypes }, WeakComponentProps3> = { foo: '' };
// const weakComponentOptionalityTest2: JSX.LibraryManagedAttributes<{ propTypes: typeof weakComponentPropTypes }, WeakComponentProps3> = { bar: true };
// interface IndexedComponentProps {
// [K: string]: boolean;
// }
// interface WeakIndexedComponentProps {
// [K: string]: any;
// }
// const weakComponentIndexedTest1: JSX.LibraryManagedAttributes<{ propTypes: typeof weakComponentPropTypes }, IndexedComponentProps> = { };
// // $ExpectError
// const weakComponentIndexedTest2: JSX.LibraryManagedAttributes<{ propTypes: typeof weakComponentPropTypes }, IndexedComponentProps> = { foo: '' };
// const weakComponentIndexedTest3: JSX.LibraryManagedAttributes<{ propTypes: typeof weakComponentPropTypes }, WeakIndexedComponentProps> = { foo: '' };
// const weakComponentIndexedTest4: JSX.LibraryManagedAttributes<{ propTypes: typeof weakComponentPropTypes }, WeakIndexedComponentProps> = { foo: 4 };