1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
|
//// [tests/cases/compiler/propTypeValidatorInference.ts] ////
//// [index.d.ts]
export const nominalTypeHack: unique symbol;
export type IsOptional<T> = undefined | null extends T ? true : undefined extends T ? true : null extends T ? true : false;
export type RequiredKeys<V> = { [K in keyof V]-?: Exclude<V[K], undefined> extends Validator<infer T> ? IsOptional<T> extends true ? never : K : never }[keyof V];
export type OptionalKeys<V> = Exclude<keyof V, RequiredKeys<V>>;
export type InferPropsInner<V> = { [K in keyof V]-?: InferType<V[K]>; };
export interface Validator<T> {
(props: object, propName: string, componentName: string, location: string, propFullName: string): Error | null;
[nominalTypeHack]?: T;
}
export interface Requireable<T> extends Validator<T> {
isRequired: Validator<NonNullable<T>>;
}
export type ValidationMap<T> = { [K in keyof T]?: Validator<T[K]> };
export type InferType<V> = V extends Validator<infer T> ? T : any;
export type InferProps<V> =
& InferPropsInner<Pick<V, RequiredKeys<V>>>
& Partial<InferPropsInner<Pick<V, OptionalKeys<V>>>>;
export const any: Requireable<any>;
export const array: Requireable<any[]>;
export const bool: Requireable<boolean>;
export const string: Requireable<string>;
export const number: Requireable<number>;
export function shape<P extends ValidationMap<any>>(type: P): Requireable<InferProps<P>>;
export function oneOfType<T extends Validator<any>>(types: T[]): Requireable<NonNullable<InferType<T>>>;
//// [file.ts]
import * as PropTypes from "prop-types";
interface Props {
any?: any;
array: string[];
bool: boolean;
shape: {
foo: string;
bar?: boolean;
baz?: any
};
oneOfType: string | boolean | {
foo?: string;
bar: number;
};
}
type PropTypesMap = PropTypes.ValidationMap<Props>;
const innerProps = {
foo: PropTypes.string.isRequired,
bar: PropTypes.bool,
baz: PropTypes.any
};
const arrayOfTypes = [PropTypes.string, PropTypes.bool, PropTypes.shape({
foo: PropTypes.string,
bar: PropTypes.number.isRequired
})];
// TS checking
const propTypes: PropTypesMap = {
any: PropTypes.any,
array: PropTypes.array.isRequired,
bool: PropTypes.bool.isRequired,
shape: PropTypes.shape(innerProps).isRequired,
oneOfType: PropTypes.oneOfType(arrayOfTypes).isRequired,
};
// JS checking
const propTypesWithoutAnnotation = {
any: PropTypes.any,
array: PropTypes.array.isRequired,
bool: PropTypes.bool.isRequired,
shape: PropTypes.shape(innerProps).isRequired,
oneOfType: PropTypes.oneOfType(arrayOfTypes).isRequired,
};
type ExtractedProps = PropTypes.InferProps<typeof propTypes>;
type ExtractedPropsWithoutAnnotation = PropTypes.InferProps<typeof propTypesWithoutAnnotation>;
type ExtractPropsMatch = ExtractedProps extends ExtractedPropsWithoutAnnotation ? true : false;
const x: true = (null as any as ExtractPropsMatch);
//// [file.js]
"use strict";
exports.__esModule = true;
var PropTypes = require("prop-types");
var innerProps = {
foo: PropTypes.string.isRequired,
bar: PropTypes.bool,
baz: PropTypes.any
};
var arrayOfTypes = [PropTypes.string, PropTypes.bool, PropTypes.shape({
foo: PropTypes.string,
bar: PropTypes.number.isRequired
})];
// TS checking
var propTypes = {
any: PropTypes.any,
array: PropTypes.array.isRequired,
bool: PropTypes.bool.isRequired,
shape: PropTypes.shape(innerProps).isRequired,
oneOfType: PropTypes.oneOfType(arrayOfTypes).isRequired
};
// JS checking
var propTypesWithoutAnnotation = {
any: PropTypes.any,
array: PropTypes.array.isRequired,
bool: PropTypes.bool.isRequired,
shape: PropTypes.shape(innerProps).isRequired,
oneOfType: PropTypes.oneOfType(arrayOfTypes).isRequired
};
var x = null;
|