diff --git a/types/airbnb-prop-types/airbnb-prop-types-tests.ts b/types/airbnb-prop-types/airbnb-prop-types-tests.ts index cf8535947e..f26aa24ed7 100644 --- a/types/airbnb-prop-types/airbnb-prop-types-tests.ts +++ b/types/airbnb-prop-types/airbnb-prop-types-tests.ts @@ -12,9 +12,9 @@ function FuncComp() { return null; } -// $ExpectType Requireable +// $ExpectType Requireable AirbnbPropTypes.and([PropTypes.number]); -// $ExpectType Requireable +// $ExpectType Requireable AirbnbPropTypes.and([PropTypes.number, AirbnbPropTypes.nonNegativeInteger]); // $ExpectType Validator AirbnbPropTypes.and([PropTypes.number, AirbnbPropTypes.integer()], 'foo').isRequired; @@ -87,7 +87,7 @@ interface ForbidShape { baz?: boolean | null; } -// $ExpectType ValidationMap<{ foo: string | null; bar: number; baz: boolean | null; }> +// $ExpectType ValidationMap<{ foo: string | null | undefined; bar: number; baz: boolean | null | undefined; }> AirbnbPropTypes.forbidExtraProps({ foo: PropTypes.string, bar: PropTypes.number.isRequired, @@ -155,7 +155,7 @@ AirbnbPropTypes.range<5>(0, 10); // $ExpectType Requireable> AirbnbPropTypes.ref(); -// $ExpectType Requireable +// $ExpectType Requireable AirbnbPropTypes.requiredBy('foo', PropTypes.string); // $ExpectType Validator AirbnbPropTypes.requiredBy('bar', PropTypes.number, 42).isRequired; @@ -177,11 +177,11 @@ interface ShapeShape { bar?: number | null; } -// $ExpectType Requireable<{ foo: string | null; }> +// $ExpectType Requireable<{ foo: string | null | undefined; }> AirbnbPropTypes.shape({ foo: PropTypes.string, }); -// $ExpectType Requireable<{ foo: string | null; bar: number | null; }> +// $ExpectType Requireable<{ foo: string | null | undefined; bar: number | null | undefined; }> AirbnbPropTypes.shape({ foo: PropTypes.string, bar: PropTypes.number, @@ -200,5 +200,5 @@ AirbnbPropTypes.uniqueArray(); // $ExpectType Requireable AirbnbPropTypes.uniqueArray(); -// $ExpectType Requireable<{ [key: string]: number | null; }> +// $ExpectType Requireable<{ [key: string]: number | null | undefined; }> AirbnbPropTypes.valuesOf(PropTypes.number); diff --git a/types/prop-types/index.d.ts b/types/prop-types/index.d.ts index e39ef68c11..3501b253d2 100644 --- a/types/prop-types/index.d.ts +++ b/types/prop-types/index.d.ts @@ -31,7 +31,7 @@ export type ReactNodeLike = export const nominalTypeHack: unique symbol; -export type IsOptional = undefined | null extends T ? true : undefined extends T ? true : null extends T ? true : false; +export type IsOptional = undefined extends T ? true : false; export type RequiredKeys = { [K in keyof V]-?: Exclude extends Validator ? IsOptional extends true ? never : K : never }[keyof V]; export type OptionalKeys = Exclude>; @@ -39,7 +39,9 @@ export type InferPropsInner = { [K in keyof V]-?: InferType; }; export interface Validator { (props: object, propName: string, componentName: string, location: string, propFullName: string): Error | null; - [nominalTypeHack]?: T; + [nominalTypeHack]?: { + type: T; + }; } export interface Requireable extends Validator { diff --git a/types/prop-types/prop-types-tests.ts b/types/prop-types/prop-types-tests.ts index e6067ee740..0f175ffdae 100644 --- a/types/prop-types/prop-types-tests.ts +++ b/types/prop-types/prop-types-tests.ts @@ -20,7 +20,7 @@ interface Props { instanceOf: TestClass; oneOf: 'a' | 'b' | 'c'; oneOfType: string | boolean | { - foo?: string; + foo?: string | null; bar: number; }; numberOrFalse: false | number; @@ -29,10 +29,12 @@ interface Props { objectOf: { [K: string]: number }; shape: { foo: string; - bar?: boolean; - baz?: any + bar?: boolean | null; + baz?: any; }; optionalNumber?: number | null; + nullableNumber: number | null; + undefinableNumber?: number; customProp?: typeof uniqueType; component: PropTypes.ReactComponentLike; } @@ -75,6 +77,8 @@ const propTypes: PropTypesMap = { objectOf: PropTypes.objectOf(PropTypes.number.isRequired).isRequired, shape: PropTypes.shape(innerProps).isRequired, optionalNumber: PropTypes.number, + nullableNumber: (() => null) as PropTypes.Validator, + undefinableNumber: (() => null) as PropTypes.Validator, customProp: (() => null) as PropTypes.Validator, component: PropTypes.elementType.isRequired }; @@ -102,6 +106,8 @@ const propTypesWithoutAnnotation = { objectOf: PropTypes.objectOf(PropTypes.number.isRequired).isRequired, shape: PropTypes.shape(innerProps).isRequired, optionalNumber: PropTypes.number, + nullableNumber: (() => null) as PropTypes.Validator, + undefinableNumber: (() => null) as PropTypes.Validator, customProp: (() => null) as PropTypes.Validator, component: PropTypes.elementType.isRequired };