// Type definitions for React 17.0 // Project: http://facebook.github.io/react/ // Definitions by: Asana // AssureSign // Microsoft // John Reilly // Benoit Benezech // Patricio Zavolinsky // Eric Anderson // Dovydas Navickas // Josh Rutherford // Guilherme Hübner // Ferdy Budhidharma // Johann Rakotoharisoa // Olivier Pascal // Martin Hochel // Frank Li // Jessica Franco // Saransh Kataria // Kanitkorn Sujautra // Sebastian Silbermann // Kyle Scully // Cong Zhang // Dimitri Mitropoulos // JongChan Choi // Victor Magalhães // Dale Tan // Priyanshu Rav // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped // TypeScript Version: 2.8 // NOTE: Users of the upcoming React 18 release should add a reference // to 'react/next' in their project. See next.d.ts's top comment // for reference and documentation on how exactly to do it. // NOTE: Users of the `experimental` builds of React should add a reference // to 'react/experimental' in their project. See experimental.d.ts's top comment // for reference and documentation on how exactly to do it. /// import * as CSS from 'csstype'; import * as PropTypes from 'prop-types'; import { Interaction as SchedulerInteraction } from 'scheduler/tracing'; type NativeAnimationEvent = AnimationEvent; type NativeClipboardEvent = ClipboardEvent; type NativeCompositionEvent = CompositionEvent; type NativeDragEvent = DragEvent; type NativeFocusEvent = FocusEvent; type NativeKeyboardEvent = KeyboardEvent; type NativeMouseEvent = MouseEvent; type NativeTouchEvent = TouchEvent; type NativePointerEvent = PointerEvent; type NativeTransitionEvent = TransitionEvent; type NativeUIEvent = UIEvent; type NativeWheelEvent = WheelEvent; type Booleanish = boolean | 'true' | 'false'; declare const UNDEFINED_VOID_ONLY: unique symbol; // Destructors are only allowed to return void. type Destructor = () => void | { [UNDEFINED_VOID_ONLY]: never }; // tslint:disable-next-line:export-just-namespace export = React; export as namespace React; declare namespace React { // // React Elements // ---------------------------------------------------------------------- type ElementType

= { [K in keyof JSX.IntrinsicElements]: P extends JSX.IntrinsicElements[K] ? K : never }[keyof JSX.IntrinsicElements] | ComponentType

; /** * @deprecated Please use `ElementType` */ type ReactType

= ElementType

; type ComponentType

= ComponentClass

| FunctionComponent

; type JSXElementConstructor

= | ((props: P) => ReactElement | null) | (new (props: P) => Component); interface RefObject { readonly current: T | null; } type RefCallback = { bivarianceHack(instance: T | null): void }["bivarianceHack"]; type Ref = RefCallback | RefObject | null; type LegacyRef = string | Ref; /** * Gets the instance type for a React element. The instance will be different for various component types: * * - React class components will be the class instance. So if you had `class Foo extends React.Component<{}> {}` * and used `React.ElementRef` then the type would be the instance of `Foo`. * - React stateless functional components do not have a backing instance and so `React.ElementRef` * (when `Bar` is `function Bar() {}`) will give you the `undefined` type. * - JSX intrinsics like `div` will give you their DOM instance. For `React.ElementRef<'div'>` that would be * `HTMLDivElement`. For `React.ElementRef<'input'>` that would be `HTMLInputElement`. * - React stateless functional components that forward a `ref` will give you the `ElementRef` of the forwarded * to component. * * `C` must be the type _of_ a React component so you need to use typeof as in React.ElementRef. * * @todo In Flow, this works a little different with forwarded refs and the `AbstractComponent` that * `React.forwardRef()` returns. */ type ElementRef< C extends | ForwardRefExoticComponent | { new (props: any): Component } | ((props: any, context?: any) => ReactElement | null) | keyof JSX.IntrinsicElements > = // need to check first if `ref` is a valid prop for ts@3.0 // otherwise it will infer `{}` instead of `never` "ref" extends keyof ComponentPropsWithRef ? NonNullable["ref"]> extends Ref< infer Instance > ? Instance : never : never; type ComponentState = any; type Key = string | number; /** * @internal You shouldn't need to use this type since you never see these attributes * inside your component or have to validate them. */ interface Attributes { key?: Key | null | undefined; } interface RefAttributes extends Attributes { ref?: Ref | undefined; } interface ClassAttributes extends Attributes { ref?: LegacyRef | undefined; } interface ReactElement

= string | JSXElementConstructor> { type: T; props: P; key: Key | null; } interface ReactComponentElement< T extends keyof JSX.IntrinsicElements | JSXElementConstructor, P = Pick, Exclude, 'key' | 'ref'>> > extends ReactElement> { } /** * @deprecated Please use `FunctionComponentElement` */ type SFCElement

= FunctionComponentElement

; interface FunctionComponentElement

extends ReactElement> { ref?: ('ref' extends keyof P ? P extends { ref?: infer R | undefined } ? R : never : never) | undefined; } type CElement> = ComponentElement; interface ComponentElement> extends ReactElement> { ref?: LegacyRef | undefined; } type ClassicElement

= CElement>; // string fallback for custom web-components interface DOMElement

| SVGAttributes, T extends Element> extends ReactElement { ref: LegacyRef; } // ReactHTML for ReactHTMLElement interface ReactHTMLElement extends DetailedReactHTMLElement, T> { } interface DetailedReactHTMLElement

, T extends HTMLElement> extends DOMElement { type: keyof ReactHTML; } // ReactSVG for ReactSVGElement interface ReactSVGElement extends DOMElement, SVGElement> { type: keyof ReactSVG; } interface ReactPortal extends ReactElement { key: Key | null; children: ReactNode; } // // Factories // ---------------------------------------------------------------------- type Factory

= (props?: Attributes & P, ...children: ReactNode[]) => ReactElement

; /** * @deprecated Please use `FunctionComponentFactory` */ type SFCFactory

= FunctionComponentFactory

; type FunctionComponentFactory

= (props?: Attributes & P, ...children: ReactNode[]) => FunctionComponentElement

; type ComponentFactory> = (props?: ClassAttributes & P, ...children: ReactNode[]) => CElement; type CFactory> = ComponentFactory; type ClassicFactory

= CFactory>; type DOMFactory

, T extends Element> = (props?: ClassAttributes & P | null, ...children: ReactNode[]) => DOMElement; interface HTMLFactory extends DetailedHTMLFactory, T> {} interface DetailedHTMLFactory

, T extends HTMLElement> extends DOMFactory { (props?: ClassAttributes & P | null, ...children: ReactNode[]): DetailedReactHTMLElement; } interface SVGFactory extends DOMFactory, SVGElement> { (props?: ClassAttributes & SVGAttributes | null, ...children: ReactNode[]): ReactSVGElement; } // // React Nodes // http://facebook.github.io/react/docs/glossary.html // ---------------------------------------------------------------------- type ReactText = string | number; type ReactChild = ReactElement | ReactText; /** * @deprecated Use either `ReactNode[]` if you need an array or `Iterable` if its passed to a host component. */ interface ReactNodeArray extends ReadonlyArray {} type ReactFragment = {} | Iterable; type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined; // // Top Level API // ---------------------------------------------------------------------- // DOM Elements function createFactory( type: keyof ReactHTML): HTMLFactory; function createFactory( type: keyof ReactSVG): SVGFactory; function createFactory

, T extends Element>( type: string): DOMFactory; // Custom components function createFactory

(type: FunctionComponent

): FunctionComponentFactory

; function createFactory

( type: ClassType, ClassicComponentClass

>): CFactory>; function createFactory, C extends ComponentClass

>( type: ClassType): CFactory; function createFactory

(type: ComponentClass

): Factory

; // DOM Elements // TODO: generalize this to everything in `keyof ReactHTML`, not just "input" function createElement( type: "input", props?: InputHTMLAttributes & ClassAttributes | null, ...children: ReactNode[]): DetailedReactHTMLElement, HTMLInputElement>; function createElement

, T extends HTMLElement>( type: keyof ReactHTML, props?: ClassAttributes & P | null, ...children: ReactNode[]): DetailedReactHTMLElement; function createElement

, T extends SVGElement>( type: keyof ReactSVG, props?: ClassAttributes & P | null, ...children: ReactNode[]): ReactSVGElement; function createElement

, T extends Element>( type: string, props?: ClassAttributes & P | null, ...children: ReactNode[]): DOMElement; // Custom components function createElement

( type: FunctionComponent

, props?: Attributes & P | null, ...children: ReactNode[]): FunctionComponentElement

; function createElement

( type: ClassType, ClassicComponentClass

>, props?: ClassAttributes> & P | null, ...children: ReactNode[]): CElement>; function createElement

, C extends ComponentClass

>( type: ClassType, props?: ClassAttributes & P | null, ...children: ReactNode[]): CElement; function createElement

( type: FunctionComponent

| ComponentClass

| string, props?: Attributes & P | null, ...children: ReactNode[]): ReactElement

; // DOM Elements // ReactHTMLElement function cloneElement

, T extends HTMLElement>( element: DetailedReactHTMLElement, props?: P, ...children: ReactNode[]): DetailedReactHTMLElement; // ReactHTMLElement, less specific function cloneElement

, T extends HTMLElement>( element: ReactHTMLElement, props?: P, ...children: ReactNode[]): ReactHTMLElement; // SVGElement function cloneElement

, T extends SVGElement>( element: ReactSVGElement, props?: P, ...children: ReactNode[]): ReactSVGElement; // DOM Element (has to be the last, because type checking stops at first overload that fits) function cloneElement

, T extends Element>( element: DOMElement, props?: DOMAttributes & P, ...children: ReactNode[]): DOMElement; // Custom components function cloneElement

( element: FunctionComponentElement

, props?: Partial

& Attributes, ...children: ReactNode[]): FunctionComponentElement

; function cloneElement>( element: CElement, props?: Partial

& ClassAttributes, ...children: ReactNode[]): CElement; function cloneElement

( element: ReactElement

, props?: Partial

& Attributes, ...children: ReactNode[]): ReactElement

; // Context via RenderProps interface ProviderProps { value: T; children?: ReactNode | undefined; } interface ConsumerProps { children: (value: T) => ReactNode; } // TODO: similar to how Fragment is actually a symbol, the values returned from createContext, // forwardRef and memo are actually objects that are treated specially by the renderer; see: // https://github.com/facebook/react/blob/v16.6.0/packages/react/src/ReactContext.js#L35-L48 // https://github.com/facebook/react/blob/v16.6.0/packages/react/src/forwardRef.js#L42-L45 // https://github.com/facebook/react/blob/v16.6.0/packages/react/src/memo.js#L27-L31 // However, we have no way of telling the JSX parser that it's a JSX element type or its props other than // by pretending to be a normal component. // // We don't just use ComponentType or FunctionComponent types because you are not supposed to attach statics to this // object, but rather to the original function. interface ExoticComponent

{ /** * **NOTE**: Exotic components are not callable. */ (props: P): (ReactElement|null); readonly $$typeof: symbol; } interface NamedExoticComponent

extends ExoticComponent

{ displayName?: string | undefined; } interface ProviderExoticComponent

extends ExoticComponent

{ propTypes?: WeakValidationMap

| undefined; } type ContextType> = C extends Context ? T : never; // NOTE: only the Context object itself can get a displayName // https://github.com/facebook/react-devtools/blob/e0b854e4c/backend/attachRendererFiber.js#L310-L325 type Provider = ProviderExoticComponent>; type Consumer = ExoticComponent>; interface Context { Provider: Provider; Consumer: Consumer; displayName?: string | undefined; } function createContext( // If you thought this should be optional, see // https://github.com/DefinitelyTyped/DefinitelyTyped/pull/24509#issuecomment-382213106 defaultValue: T, ): Context; function isValidElement

(object: {} | null | undefined): object is ReactElement

; const Children: ReactChildren; const Fragment: ExoticComponent<{ children?: ReactNode | undefined }>; const StrictMode: ExoticComponent<{ children?: ReactNode | undefined }>; interface SuspenseProps { children?: ReactNode | undefined; // TODO(react18): `fallback?: ReactNode;` /** A fallback react tree to show when a Suspense child (like React.lazy) suspends */ fallback: NonNullable|null; } // TODO(react18): Updated JSDoc to reflect that Suspense works on the server. /** * This feature is not yet available for server-side rendering. * Suspense support will be added in a later release. */ const Suspense: ExoticComponent; const version: string; /** * {@link https://reactjs.org/docs/profiler.html#onrender-callback Profiler API} */ type ProfilerOnRenderCallback = ( id: string, phase: "mount" | "update", actualDuration: number, baseDuration: number, startTime: number, commitTime: number, interactions: Set, ) => void; interface ProfilerProps { children?: ReactNode | undefined; id: string; onRender: ProfilerOnRenderCallback; } const Profiler: ExoticComponent; // // Component API // ---------------------------------------------------------------------- type ReactInstance = Component | Element; // Base component for plain JS classes interface Component

extends ComponentLifecycle { } class Component { // tslint won't let me format the sample code in a way that vscode likes it :( /** * If set, `this.context` will be set at runtime to the current value of the given Context. * * Usage: * * ```ts * type MyContext = number * const Ctx = React.createContext(0) * * class Foo extends React.Component { * static contextType = Ctx * context!: React.ContextType * render () { * return <>My context's value: {this.context}; * } * } * ``` * * @see https://reactjs.org/docs/context.html#classcontexttype */ static contextType?: Context | undefined; /** * If using the new style context, re-declare this in your class to be the * `React.ContextType` of your `static contextType`. * Should be used with type annotation or static contextType. * * ```ts * static contextType = MyContext * // For TS pre-3.7: * context!: React.ContextType * // For TS 3.7 and above: * declare context: React.ContextType * ``` * * @see https://reactjs.org/docs/context.html */ // TODO (TypeScript 3.0): unknown context: any; constructor(props: Readonly

| P); /** * @deprecated * @see https://reactjs.org/docs/legacy-context.html */ constructor(props: P, context: any); // We MUST keep setState() as a unified signature because it allows proper checking of the method return type. // See: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/18365#issuecomment-351013257 // Also, the ` | S` allows intellisense to not be dumbisense setState( state: ((prevState: Readonly, props: Readonly

) => (Pick | S | null)) | (Pick | S | null), callback?: () => void ): void; forceUpdate(callback?: () => void): void; render(): ReactNode; // React.Props is now deprecated, which means that the `children` // property is not available on `P` by default, even though you can // always pass children as variadic arguments to `createElement`. // In the future, if we can define its call signature conditionally // on the existence of `children` in `P`, then we should remove this. readonly props: Readonly

& Readonly<{ children?: ReactNode | undefined }>; state: Readonly; /** * @deprecated * https://reactjs.org/docs/refs-and-the-dom.html#legacy-api-string-refs */ refs: { [key: string]: ReactInstance }; } class PureComponent

extends Component { } interface ClassicComponent

extends Component { replaceState(nextState: S, callback?: () => void): void; isMounted(): boolean; getInitialState?(): S; } interface ChildContextProvider { getChildContext(): CC; } // // Class Interfaces // ---------------------------------------------------------------------- /** * @deprecated as of recent React versions, function components can no * longer be considered 'stateless'. Please use `FunctionComponent` instead. * * @see [React Hooks](https://reactjs.org/docs/hooks-intro.html) */ type SFC

= FunctionComponent

; /** * @deprecated as of recent React versions, function components can no * longer be considered 'stateless'. Please use `FunctionComponent` instead. * * @see [React Hooks](https://reactjs.org/docs/hooks-intro.html) */ type StatelessComponent

= FunctionComponent

; type FC

= FunctionComponent

; interface FunctionComponent

{ (props: PropsWithChildren

, context?: any): ReactElement | null; propTypes?: WeakValidationMap

| undefined; contextTypes?: ValidationMap | undefined; defaultProps?: Partial

| undefined; displayName?: string | undefined; } type VFC

= VoidFunctionComponent

; interface VoidFunctionComponent

{ (props: P, context?: any): ReactElement | null; propTypes?: WeakValidationMap

| undefined; contextTypes?: ValidationMap | undefined; defaultProps?: Partial

| undefined; displayName?: string | undefined; } type ForwardedRef = ((instance: T | null) => void) | MutableRefObject | null; interface ForwardRefRenderFunction { (props: PropsWithChildren

, ref: ForwardedRef): ReactElement | null; displayName?: string | undefined; // explicit rejected with `never` required due to // https://github.com/microsoft/TypeScript/issues/36826 /** * defaultProps are not supported on render functions */ defaultProps?: never | undefined; /** * propTypes are not supported on render functions */ propTypes?: never | undefined; } /** * @deprecated Use ForwardRefRenderFunction. forwardRef doesn't accept a * "real" component. */ interface RefForwardingComponent extends ForwardRefRenderFunction {} interface ComponentClass

extends StaticLifecycle { new (props: P, context?: any): Component; propTypes?: WeakValidationMap

| undefined; contextType?: Context | undefined; contextTypes?: ValidationMap | undefined; childContextTypes?: ValidationMap | undefined; defaultProps?: Partial

| undefined; displayName?: string | undefined; } interface ClassicComponentClass

extends ComponentClass

{ new (props: P, context?: any): ClassicComponent; getDefaultProps?(): P; } /** * We use an intersection type to infer multiple type parameters from * a single argument, which is useful for many top-level API defs. * See https://github.com/Microsoft/TypeScript/issues/7234 for more info. */ type ClassType, C extends ComponentClass

> = C & (new (props: P, context?: any) => T); // // Component Specs and Lifecycle // ---------------------------------------------------------------------- // This should actually be something like `Lifecycle | DeprecatedLifecycle`, // as React will _not_ call the deprecated lifecycle methods if any of the new lifecycle // methods are present. interface ComponentLifecycle extends NewLifecycle, DeprecatedLifecycle { /** * Called immediately after a component is mounted. Setting state here will trigger re-rendering. */ componentDidMount?(): void; /** * Called to determine whether the change in props and state should trigger a re-render. * * `Component` always returns true. * `PureComponent` implements a shallow comparison on props and state and returns true if any * props or states have changed. * * If false is returned, `Component#render`, `componentWillUpdate` * and `componentDidUpdate` will not be called. */ shouldComponentUpdate?(nextProps: Readonly

, nextState: Readonly, nextContext: any): boolean; /** * Called immediately before a component is destroyed. Perform any necessary cleanup in this method, such as * cancelled network requests, or cleaning up any DOM elements created in `componentDidMount`. */ componentWillUnmount?(): void; /** * Catches exceptions generated in descendant components. Unhandled exceptions will cause * the entire component tree to unmount. */ componentDidCatch?(error: Error, errorInfo: ErrorInfo): void; } // Unfortunately, we have no way of declaring that the component constructor must implement this interface StaticLifecycle { getDerivedStateFromProps?: GetDerivedStateFromProps | undefined; getDerivedStateFromError?: GetDerivedStateFromError | undefined; } type GetDerivedStateFromProps = /** * Returns an update to a component's state based on its new props and old state. * * Note: its presence prevents any of the deprecated lifecycle methods from being invoked */ (nextProps: Readonly

, prevState: S) => Partial | null; type GetDerivedStateFromError = /** * This lifecycle is invoked after an error has been thrown by a descendant component. * It receives the error that was thrown as a parameter and should return a value to update state. * * Note: its presence prevents any of the deprecated lifecycle methods from being invoked */ (error: any) => Partial | null; // This should be "infer SS" but can't use it yet interface NewLifecycle { /** * Runs before React applies the result of `render` to the document, and * returns an object to be given to componentDidUpdate. Useful for saving * things such as scroll position before `render` causes changes to it. * * Note: the presence of getSnapshotBeforeUpdate prevents any of the deprecated * lifecycle events from running. */ getSnapshotBeforeUpdate?(prevProps: Readonly

, prevState: Readonly): SS | null; /** * Called immediately after updating occurs. Not called for the initial render. * * The snapshot is only present if getSnapshotBeforeUpdate is present and returns non-null. */ componentDidUpdate?(prevProps: Readonly

, prevState: Readonly, snapshot?: SS): void; } interface DeprecatedLifecycle { /** * Called immediately before mounting occurs, and before `Component#render`. * Avoid introducing any side-effects or subscriptions in this method. * * Note: the presence of getSnapshotBeforeUpdate or getDerivedStateFromProps * prevents this from being invoked. * * @deprecated 16.3, use componentDidMount or the constructor instead; will stop working in React 17 * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#initializing-state * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path */ componentWillMount?(): void; /** * Called immediately before mounting occurs, and before `Component#render`. * Avoid introducing any side-effects or subscriptions in this method. * * This method will not stop working in React 17. * * Note: the presence of getSnapshotBeforeUpdate or getDerivedStateFromProps * prevents this from being invoked. * * @deprecated 16.3, use componentDidMount or the constructor instead * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#initializing-state * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path */ UNSAFE_componentWillMount?(): void; /** * Called when the component may be receiving new props. * React may call this even if props have not changed, so be sure to compare new and existing * props if you only want to handle changes. * * Calling `Component#setState` generally does not trigger this method. * * Note: the presence of getSnapshotBeforeUpdate or getDerivedStateFromProps * prevents this from being invoked. * * @deprecated 16.3, use static getDerivedStateFromProps instead; will stop working in React 17 * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#updating-state-based-on-props * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path */ componentWillReceiveProps?(nextProps: Readonly

, nextContext: any): void; /** * Called when the component may be receiving new props. * React may call this even if props have not changed, so be sure to compare new and existing * props if you only want to handle changes. * * Calling `Component#setState` generally does not trigger this method. * * This method will not stop working in React 17. * * Note: the presence of getSnapshotBeforeUpdate or getDerivedStateFromProps * prevents this from being invoked. * * @deprecated 16.3, use static getDerivedStateFromProps instead * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#updating-state-based-on-props * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path */ UNSAFE_componentWillReceiveProps?(nextProps: Readonly

, nextContext: any): void; /** * Called immediately before rendering when new props or state is received. Not called for the initial render. * * Note: You cannot call `Component#setState` here. * * Note: the presence of getSnapshotBeforeUpdate or getDerivedStateFromProps * prevents this from being invoked. * * @deprecated 16.3, use getSnapshotBeforeUpdate instead; will stop working in React 17 * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#reading-dom-properties-before-an-update * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path */ componentWillUpdate?(nextProps: Readonly

, nextState: Readonly, nextContext: any): void; /** * Called immediately before rendering when new props or state is received. Not called for the initial render. * * Note: You cannot call `Component#setState` here. * * This method will not stop working in React 17. * * Note: the presence of getSnapshotBeforeUpdate or getDerivedStateFromProps * prevents this from being invoked. * * @deprecated 16.3, use getSnapshotBeforeUpdate instead * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#reading-dom-properties-before-an-update * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path */ UNSAFE_componentWillUpdate?(nextProps: Readonly

, nextState: Readonly, nextContext: any): void; } interface Mixin extends ComponentLifecycle { mixins?: Array> | undefined; statics?: { [key: string]: any; } | undefined; displayName?: string | undefined; propTypes?: ValidationMap | undefined; contextTypes?: ValidationMap | undefined; childContextTypes?: ValidationMap | undefined; getDefaultProps?(): P; getInitialState?(): S; } interface ComponentSpec extends Mixin { render(): ReactNode; [propertyName: string]: any; } function createRef(): RefObject; // will show `ForwardRef(${Component.displayName || Component.name})` in devtools by default, // but can be given its own specific name interface ForwardRefExoticComponent

extends NamedExoticComponent

{ defaultProps?: Partial

| undefined; propTypes?: WeakValidationMap

| undefined; } function forwardRef(render: ForwardRefRenderFunction): ForwardRefExoticComponent & RefAttributes>; /** Ensures that the props do not include ref at all */ type PropsWithoutRef

= // Pick would not be sufficient for this. We'd like to avoid unnecessary mapping and need a distributive conditional to support unions. // see: https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types // https://github.com/Microsoft/TypeScript/issues/28339 P extends any ? ('ref' extends keyof P ? Pick> : P) : P; /** Ensures that the props do not include string ref, which cannot be forwarded */ type PropsWithRef

= // Just "P extends { ref?: infer R }" looks sufficient, but R will infer as {} if P is {}. 'ref' extends keyof P ? P extends { ref?: infer R | undefined } ? string extends R ? PropsWithoutRef

& { ref?: Exclude | undefined } : P : P : P; type PropsWithChildren

= P & { children?: ReactNode | undefined }; /** * NOTE: prefer ComponentPropsWithRef, if the ref is forwarded, * or ComponentPropsWithoutRef when refs are not supported. */ type ComponentProps> = T extends JSXElementConstructor ? P : T extends keyof JSX.IntrinsicElements ? JSX.IntrinsicElements[T] : {}; type ComponentPropsWithRef = T extends (new (props: infer P) => Component) ? PropsWithoutRef

& RefAttributes> : PropsWithRef>; type ComponentPropsWithoutRef = PropsWithoutRef>; type ComponentRef = T extends NamedExoticComponent< ComponentPropsWithoutRef & RefAttributes > ? Method : ComponentPropsWithRef extends RefAttributes ? Method : never; // will show `Memo(${Component.displayName || Component.name})` in devtools by default, // but can be given its own specific name type MemoExoticComponent> = NamedExoticComponent> & { readonly type: T; }; function memo

( Component: FunctionComponent

, propsAreEqual?: (prevProps: Readonly>, nextProps: Readonly>) => boolean ): NamedExoticComponent

; function memo>( Component: T, propsAreEqual?: (prevProps: Readonly>, nextProps: Readonly>) => boolean ): MemoExoticComponent; type LazyExoticComponent> = ExoticComponent> & { readonly _result: T; }; function lazy>( factory: () => Promise<{ default: T }> ): LazyExoticComponent; // // React Hooks // ---------------------------------------------------------------------- // based on the code in https://github.com/facebook/react/pull/13968 // Unlike the class component setState, the updates are not allowed to be partial type SetStateAction = S | ((prevState: S) => S); // this technically does accept a second argument, but it's already under a deprecation warning // and it's not even released so probably better to not define it. type Dispatch = (value: A) => void; // Since action _can_ be undefined, dispatch may be called without any parameters. type DispatchWithoutAction = () => void; // Unlike redux, the actions _can_ be anything type Reducer = (prevState: S, action: A) => S; // If useReducer accepts a reducer without action, dispatch may be called without any parameters. type ReducerWithoutAction = (prevState: S) => S; // types used to try and prevent the compiler from reducing S // to a supertype common with the second argument to useReducer() type ReducerState> = R extends Reducer ? S : never; type ReducerAction> = R extends Reducer ? A : never; // The identity check is done with the SameValue algorithm (Object.is), which is stricter than === type ReducerStateWithoutAction> = R extends ReducerWithoutAction ? S : never; // TODO (TypeScript 3.0): ReadonlyArray type DependencyList = ReadonlyArray; // NOTE: callbacks are _only_ allowed to return either void, or a destructor. type EffectCallback = () => (void | Destructor); interface MutableRefObject { current: T; } // This will technically work if you give a Consumer or Provider but it's deprecated and warns /** * Accepts a context object (the value returned from `React.createContext`) and returns the current * context value, as given by the nearest context provider for the given context. * * @version 16.8.0 * @see https://reactjs.org/docs/hooks-reference.html#usecontext */ function useContext(context: Context/*, (not public API) observedBits?: number|boolean */): T; /** * Returns a stateful value, and a function to update it. * * @version 16.8.0 * @see https://reactjs.org/docs/hooks-reference.html#usestate */ function useState(initialState: S | (() => S)): [S, Dispatch>]; // convenience overload when first argument is omitted /** * Returns a stateful value, and a function to update it. * * @version 16.8.0 * @see https://reactjs.org/docs/hooks-reference.html#usestate */ function useState(): [S | undefined, Dispatch>]; /** * An alternative to `useState`. * * `useReducer` is usually preferable to `useState` when you have complex state logic that involves * multiple sub-values. It also lets you optimize performance for components that trigger deep * updates because you can pass `dispatch` down instead of callbacks. * * @version 16.8.0 * @see https://reactjs.org/docs/hooks-reference.html#usereducer */ // overload where dispatch could accept 0 arguments. function useReducer, I>( reducer: R, initializerArg: I, initializer: (arg: I) => ReducerStateWithoutAction ): [ReducerStateWithoutAction, DispatchWithoutAction]; /** * An alternative to `useState`. * * `useReducer` is usually preferable to `useState` when you have complex state logic that involves * multiple sub-values. It also lets you optimize performance for components that trigger deep * updates because you can pass `dispatch` down instead of callbacks. * * @version 16.8.0 * @see https://reactjs.org/docs/hooks-reference.html#usereducer */ // overload where dispatch could accept 0 arguments. function useReducer>( reducer: R, initializerArg: ReducerStateWithoutAction, initializer?: undefined ): [ReducerStateWithoutAction, DispatchWithoutAction]; /** * An alternative to `useState`. * * `useReducer` is usually preferable to `useState` when you have complex state logic that involves * multiple sub-values. It also lets you optimize performance for components that trigger deep * updates because you can pass `dispatch` down instead of callbacks. * * @version 16.8.0 * @see https://reactjs.org/docs/hooks-reference.html#usereducer */ // overload where "I" may be a subset of ReducerState; used to provide autocompletion. // If "I" matches ReducerState exactly then the last overload will allow initializer to be omitted. // the last overload effectively behaves as if the identity function (x => x) is the initializer. function useReducer, I>( reducer: R, initializerArg: I & ReducerState, initializer: (arg: I & ReducerState) => ReducerState ): [ReducerState, Dispatch>]; /** * An alternative to `useState`. * * `useReducer` is usually preferable to `useState` when you have complex state logic that involves * multiple sub-values. It also lets you optimize performance for components that trigger deep * updates because you can pass `dispatch` down instead of callbacks. * * @version 16.8.0 * @see https://reactjs.org/docs/hooks-reference.html#usereducer */ // overload for free "I"; all goes as long as initializer converts it into "ReducerState". function useReducer, I>( reducer: R, initializerArg: I, initializer: (arg: I) => ReducerState ): [ReducerState, Dispatch>]; /** * An alternative to `useState`. * * `useReducer` is usually preferable to `useState` when you have complex state logic that involves * multiple sub-values. It also lets you optimize performance for components that trigger deep * updates because you can pass `dispatch` down instead of callbacks. * * @version 16.8.0 * @see https://reactjs.org/docs/hooks-reference.html#usereducer */ // I'm not sure if I keep this 2-ary or if I make it (2,3)-ary; it's currently (2,3)-ary. // The Flow types do have an overload for 3-ary invocation with undefined initializer. // NOTE: without the ReducerState indirection, TypeScript would reduce S to be the most common // supertype between the reducer's return type and the initialState (or the initializer's return type), // which would prevent autocompletion from ever working. // TODO: double-check if this weird overload logic is necessary. It is possible it's either a bug // in older versions, or a regression in newer versions of the typescript completion service. function useReducer>( reducer: R, initialState: ReducerState, initializer?: undefined ): [ReducerState, Dispatch>]; /** * `useRef` returns a mutable ref object whose `.current` property is initialized to the passed argument * (`initialValue`). The returned object will persist for the full lifetime of the component. * * Note that `useRef()` is useful for more than the `ref` attribute. It’s handy for keeping any mutable * value around similar to how you’d use instance fields in classes. * * @version 16.8.0 * @see https://reactjs.org/docs/hooks-reference.html#useref */ function useRef(initialValue: T): MutableRefObject; // convenience overload for refs given as a ref prop as they typically start with a null value /** * `useRef` returns a mutable ref object whose `.current` property is initialized to the passed argument * (`initialValue`). The returned object will persist for the full lifetime of the component. * * Note that `useRef()` is useful for more than the `ref` attribute. It’s handy for keeping any mutable * value around similar to how you’d use instance fields in classes. * * Usage note: if you need the result of useRef to be directly mutable, include `| null` in the type * of the generic argument. * * @version 16.8.0 * @see https://reactjs.org/docs/hooks-reference.html#useref */ function useRef(initialValue: T|null): RefObject; // convenience overload for potentially undefined initialValue / call with 0 arguments // has a default to stop it from defaulting to {} instead /** * `useRef` returns a mutable ref object whose `.current` property is initialized to the passed argument * (`initialValue`). The returned object will persist for the full lifetime of the component. * * Note that `useRef()` is useful for more than the `ref` attribute. It’s handy for keeping any mutable * value around similar to how you’d use instance fields in classes. * * @version 16.8.0 * @see https://reactjs.org/docs/hooks-reference.html#useref */ function useRef(): MutableRefObject; /** * The signature is identical to `useEffect`, but it fires synchronously after all DOM mutations. * Use this to read layout from the DOM and synchronously re-render. Updates scheduled inside * `useLayoutEffect` will be flushed synchronously, before the browser has a chance to paint. * * Prefer the standard `useEffect` when possible to avoid blocking visual updates. * * If you’re migrating code from a class component, `useLayoutEffect` fires in the same phase as * `componentDidMount` and `componentDidUpdate`. * * @version 16.8.0 * @see https://reactjs.org/docs/hooks-reference.html#uselayouteffect */ function useLayoutEffect(effect: EffectCallback, deps?: DependencyList): void; /** * Accepts a function that contains imperative, possibly effectful code. * * @param effect Imperative function that can return a cleanup function * @param deps If present, effect will only activate if the values in the list change. * * @version 16.8.0 * @see https://reactjs.org/docs/hooks-reference.html#useeffect */ function useEffect(effect: EffectCallback, deps?: DependencyList): void; // NOTE: this does not accept strings, but this will have to be fixed by removing strings from type Ref /** * `useImperativeHandle` customizes the instance value that is exposed to parent components when using * `ref`. As always, imperative code using refs should be avoided in most cases. * * `useImperativeHandle` should be used with `React.forwardRef`. * * @version 16.8.0 * @see https://reactjs.org/docs/hooks-reference.html#useimperativehandle */ function useImperativeHandle(ref: Ref|undefined, init: () => R, deps?: DependencyList): void; // I made 'inputs' required here and in useMemo as there's no point to memoizing without the memoization key // useCallback(X) is identical to just using X, useMemo(() => Y) is identical to just using Y. /** * `useCallback` will return a memoized version of the callback that only changes if one of the `inputs` * has changed. * * @version 16.8.0 * @see https://reactjs.org/docs/hooks-reference.html#usecallback */ // TODO (TypeScript 3.0): unknown> function useCallback any>(callback: T, deps: DependencyList): T; /** * `useMemo` will only recompute the memoized value when one of the `deps` has changed. * * Usage note: if calling `useMemo` with a referentially stable function, also give it as the input in * the second argument. * * ```ts * function expensive () { ... } * * function Component () { * const expensiveResult = useMemo(expensive, [expensive]) * return ... * } * ``` * * @version 16.8.0 * @see https://reactjs.org/docs/hooks-reference.html#usememo */ // allow undefined, but don't make it optional as that is very likely a mistake function useMemo(factory: () => T, deps: DependencyList | undefined): T; /** * `useDebugValue` can be used to display a label for custom hooks in React DevTools. * * NOTE: We don’t recommend adding debug values to every custom hook. * It’s most valuable for custom hooks that are part of shared libraries. * * @version 16.8.0 * @see https://reactjs.org/docs/hooks-reference.html#usedebugvalue */ // the name of the custom hook is itself derived from the function name at runtime: // it's just the function name without the "use" prefix. function useDebugValue(value: T, format?: (value: T) => any): void; // // Event System // ---------------------------------------------------------------------- // TODO: change any to unknown when moving to TS v3 interface BaseSyntheticEvent { nativeEvent: E; currentTarget: C; target: T; bubbles: boolean; cancelable: boolean; defaultPrevented: boolean; eventPhase: number; isTrusted: boolean; preventDefault(): void; isDefaultPrevented(): boolean; stopPropagation(): void; isPropagationStopped(): boolean; persist(): void; timeStamp: number; type: string; } /** * currentTarget - a reference to the element on which the event listener is registered. * * target - a reference to the element from which the event was originally dispatched. * This might be a child element to the element on which the event listener is registered. * If you thought this should be `EventTarget & T`, see https://github.com/DefinitelyTyped/DefinitelyTyped/issues/11508#issuecomment-256045682 */ interface SyntheticEvent extends BaseSyntheticEvent {} interface ClipboardEvent extends SyntheticEvent { clipboardData: DataTransfer; } interface CompositionEvent extends SyntheticEvent { data: string; } interface DragEvent extends MouseEvent { dataTransfer: DataTransfer; } interface PointerEvent extends MouseEvent { pointerId: number; pressure: number; tangentialPressure: number; tiltX: number; tiltY: number; twist: number; width: number; height: number; pointerType: 'mouse' | 'pen' | 'touch'; isPrimary: boolean; } interface FocusEvent extends SyntheticEvent { relatedTarget: (EventTarget & RelatedTarget) | null; target: EventTarget & Target; } interface FormEvent extends SyntheticEvent { } interface InvalidEvent extends SyntheticEvent { target: EventTarget & T; } interface ChangeEvent extends SyntheticEvent { target: EventTarget & T; } interface KeyboardEvent extends UIEvent { altKey: boolean; /** @deprecated */ charCode: number; ctrlKey: boolean; code: string; /** * See [DOM Level 3 Events spec](https://www.w3.org/TR/uievents-key/#keys-modifier). for a list of valid (case-sensitive) arguments to this method. */ getModifierState(key: string): boolean; /** * See the [DOM Level 3 Events spec](https://www.w3.org/TR/uievents-key/#named-key-attribute-values). for possible values */ key: string; /** @deprecated */ keyCode: number; locale: string; location: number; metaKey: boolean; repeat: boolean; shiftKey: boolean; /** @deprecated */ which: number; } interface MouseEvent extends UIEvent { altKey: boolean; button: number; buttons: number; clientX: number; clientY: number; ctrlKey: boolean; /** * See [DOM Level 3 Events spec](https://www.w3.org/TR/uievents-key/#keys-modifier). for a list of valid (case-sensitive) arguments to this method. */ getModifierState(key: string): boolean; metaKey: boolean; movementX: number; movementY: number; pageX: number; pageY: number; relatedTarget: EventTarget | null; screenX: number; screenY: number; shiftKey: boolean; } interface TouchEvent extends UIEvent { altKey: boolean; changedTouches: TouchList; ctrlKey: boolean; /** * See [DOM Level 3 Events spec](https://www.w3.org/TR/uievents-key/#keys-modifier). for a list of valid (case-sensitive) arguments to this method. */ getModifierState(key: string): boolean; metaKey: boolean; shiftKey: boolean; targetTouches: TouchList; touches: TouchList; } interface UIEvent extends SyntheticEvent { detail: number; view: AbstractView; } interface WheelEvent extends MouseEvent { deltaMode: number; deltaX: number; deltaY: number; deltaZ: number; } interface AnimationEvent extends SyntheticEvent { animationName: string; elapsedTime: number; pseudoElement: string; } interface TransitionEvent extends SyntheticEvent { elapsedTime: number; propertyName: string; pseudoElement: string; } // // Event Handler Types // ---------------------------------------------------------------------- type EventHandler> = { bivarianceHack(event: E): void }["bivarianceHack"]; type ReactEventHandler = EventHandler>; type ClipboardEventHandler = EventHandler>; type CompositionEventHandler = EventHandler>; type DragEventHandler = EventHandler>; type FocusEventHandler = EventHandler>; type FormEventHandler = EventHandler>; type ChangeEventHandler = EventHandler>; type KeyboardEventHandler = EventHandler>; type MouseEventHandler = EventHandler>; type TouchEventHandler = EventHandler>; type PointerEventHandler = EventHandler>; type UIEventHandler = EventHandler>; type WheelEventHandler = EventHandler>; type AnimationEventHandler = EventHandler>; type TransitionEventHandler = EventHandler>; // // Props / DOM Attributes // ---------------------------------------------------------------------- /** * @deprecated. This was used to allow clients to pass `ref` and `key` * to `createElement`, which is no longer necessary due to intersection * types. If you need to declare a props object before passing it to * `createElement` or a factory, use `ClassAttributes`: * * ```ts * var b: Button | null; * var props: ButtonProps & ClassAttributes