@types/react
Version:
TypeScript definitions for react
1,145 lines (1,034 loc) • 160 kB
TypeScript
// 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.
/// <reference path="global.d.ts" />
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";
type CrossOrigin = "anonymous" | "use-credentials" | "" | undefined;
declare const UNDEFINED_VOID_ONLY: unique symbol;
// Destructors are only allowed to return void.
type Destructor = () => void | { [UNDEFINED_VOID_ONLY]: never };
type VoidOrUndefinedOnly = void | { [UNDEFINED_VOID_ONLY]: never };
// eslint-disable-next-line @definitelytyped/export-just-namespace
export = React;
export as namespace React;
declare namespace React {
//
// React Elements
// ----------------------------------------------------------------------
type ElementType<P = any> =
| {
[K in keyof JSX.IntrinsicElements]: P extends JSX.IntrinsicElements[K] ? K : never;
}[keyof JSX.IntrinsicElements]
| ComponentType<P>;
type ComponentType<P = {}> = ComponentClass<P> | FunctionComponent<P>;
type JSXElementConstructor<P> =
| ((
props: P,
/**
* @deprecated https://legacy.reactjs.org/docs/legacy-context.html#referencing-context-in-stateless-function-components
*/
deprecatedLegacyContext?: any,
) => ReactNode)
| (new(
props: P,
/**
* @deprecated https://legacy.reactjs.org/docs/legacy-context.html#referencing-context-in-lifecycle-methods
*/
deprecatedLegacyContext?: any,
) => Component<any, any>);
interface RefObject<T> {
readonly current: T | null;
}
// Bivariance hack for consistent unsoundness with RefObject
type RefCallback<T> = { bivarianceHack(instance: T | null): void }["bivarianceHack"];
type Ref<T> = RefCallback<T> | RefObject<T> | null;
type LegacyRef<T> = string | Ref<T>;
/**
* 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<typeof Foo>` then the type would be the instance of `Foo`.
* - React stateless functional components do not have a backing instance and so `React.ElementRef<typeof Bar>`
* (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<typeof MyComponent>`.
*
* @todo In Flow, this works a little different with forwarded refs and the `AbstractComponent` that
* `React.forwardRef()` returns.
*/
type ElementRef<
C extends
| ForwardRefExoticComponent<any>
| { new(props: any): Component<any> }
| ((props: any, context?: any) => ReactNode)
| 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<C> ? NonNullable<ComponentPropsWithRef<C>["ref"]> extends Ref<
infer Instance
> ? Instance
: never
: never;
type ComponentState = any;
type Key = string | number | bigint;
/**
* @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<T> extends Attributes {
/**
* Allows getting a ref to the component instance.
* Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
* @see https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom
*/
ref?: Ref<T> | undefined;
}
interface ClassAttributes<T> extends Attributes {
/**
* Allows getting a ref to the component instance.
* Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
* @see https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom
*/
ref?: LegacyRef<T> | undefined;
}
interface ReactElement<
P = any,
T extends string | JSXElementConstructor<any> = string | JSXElementConstructor<any>,
> {
type: T;
props: P;
key: string | null;
}
interface ReactComponentElement<
T extends keyof JSX.IntrinsicElements | JSXElementConstructor<any>,
P = Pick<ComponentProps<T>, Exclude<keyof ComponentProps<T>, "key" | "ref">>,
> extends ReactElement<P, Exclude<T, number>> {}
interface FunctionComponentElement<P> extends ReactElement<P, FunctionComponent<P>> {
ref?: ("ref" extends keyof P ? P extends { ref?: infer R | undefined } ? R : never : never) | undefined;
}
type CElement<P, T extends Component<P, ComponentState>> = ComponentElement<P, T>;
interface ComponentElement<P, T extends Component<P, ComponentState>> extends ReactElement<P, ComponentClass<P>> {
ref?: LegacyRef<T> | undefined;
}
type ClassicElement<P> = CElement<P, ClassicComponent<P, ComponentState>>;
// string fallback for custom web-components
interface DOMElement<P extends HTMLAttributes<T> | SVGAttributes<T>, T extends Element>
extends ReactElement<P, string>
{
ref: LegacyRef<T>;
}
// ReactHTML for ReactHTMLElement
interface ReactHTMLElement<T extends HTMLElement> extends DetailedReactHTMLElement<AllHTMLAttributes<T>, T> {}
interface DetailedReactHTMLElement<P extends HTMLAttributes<T>, T extends HTMLElement> extends DOMElement<P, T> {
type: keyof ReactHTML;
}
// ReactSVG for ReactSVGElement
interface ReactSVGElement extends DOMElement<SVGAttributes<SVGElement>, SVGElement> {
type: keyof ReactSVG;
}
interface ReactPortal extends ReactElement {
children: ReactNode;
}
//
// Factories
// ----------------------------------------------------------------------
type Factory<P> = (props?: Attributes & P, ...children: ReactNode[]) => ReactElement<P>;
/**
* @deprecated Please use `FunctionComponentFactory`
*/
type SFCFactory<P> = FunctionComponentFactory<P>;
type FunctionComponentFactory<P> = (
props?: Attributes & P,
...children: ReactNode[]
) => FunctionComponentElement<P>;
type ComponentFactory<P, T extends Component<P, ComponentState>> = (
props?: ClassAttributes<T> & P,
...children: ReactNode[]
) => CElement<P, T>;
type CFactory<P, T extends Component<P, ComponentState>> = ComponentFactory<P, T>;
type ClassicFactory<P> = CFactory<P, ClassicComponent<P, ComponentState>>;
type DOMFactory<P extends DOMAttributes<T>, T extends Element> = (
props?: ClassAttributes<T> & P | null,
...children: ReactNode[]
) => DOMElement<P, T>;
interface HTMLFactory<T extends HTMLElement> extends DetailedHTMLFactory<AllHTMLAttributes<T>, T> {}
interface DetailedHTMLFactory<P extends HTMLAttributes<T>, T extends HTMLElement> extends DOMFactory<P, T> {
(props?: ClassAttributes<T> & P | null, ...children: ReactNode[]): DetailedReactHTMLElement<P, T>;
}
interface SVGFactory extends DOMFactory<SVGAttributes<SVGElement>, SVGElement> {
(
props?: ClassAttributes<SVGElement> & SVGAttributes<SVGElement> | null,
...children: ReactNode[]
): ReactSVGElement;
}
/**
* @deprecated - This type is not relevant when using React. Inline the type instead to make the intent clear.
*/
type ReactText = string | number;
/**
* @deprecated - This type is not relevant when using React. Inline the type instead to make the intent clear.
*/
type ReactChild = ReactElement | string | number;
/**
* @deprecated Use either `ReactNode[]` if you need an array or `Iterable<ReactNode>` if its passed to a host component.
*/
interface ReactNodeArray extends ReadonlyArray<ReactNode> {}
/**
* @deprecated - This type is not relevant when using React. Inline the type instead to make the intent clear.
*/
type ReactFragment = Iterable<ReactNode>;
/**
* For internal usage only.
* Different release channels declare additional types of ReactNode this particular release channel accepts.
* App or library types should never augment this interface.
*/
interface DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_REACT_NODES {}
type ReactNode =
| ReactElement
| string
| number
| Iterable<ReactNode>
| ReactPortal
| boolean
| null
| undefined
| DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_REACT_NODES[
keyof DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_REACT_NODES
];
//
// Top Level API
// ----------------------------------------------------------------------
// DOM Elements
function createFactory<T extends HTMLElement>(
type: keyof ReactHTML,
): HTMLFactory<T>;
function createFactory(
type: keyof ReactSVG,
): SVGFactory;
function createFactory<P extends DOMAttributes<T>, T extends Element>(
type: string,
): DOMFactory<P, T>;
// Custom components
function createFactory<P>(type: FunctionComponent<P>): FunctionComponentFactory<P>;
function createFactory<P>(
type: ClassType<P, ClassicComponent<P, ComponentState>, ClassicComponentClass<P>>,
): CFactory<P, ClassicComponent<P, ComponentState>>;
function createFactory<P, T extends Component<P, ComponentState>, C extends ComponentClass<P>>(
type: ClassType<P, T, C>,
): CFactory<P, T>;
function createFactory<P>(type: ComponentClass<P>): Factory<P>;
// DOM Elements
// TODO: generalize this to everything in `keyof ReactHTML`, not just "input"
function createElement(
type: "input",
props?: InputHTMLAttributes<HTMLInputElement> & ClassAttributes<HTMLInputElement> | null,
...children: ReactNode[]
): DetailedReactHTMLElement<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>;
function createElement<P extends HTMLAttributes<T>, T extends HTMLElement>(
type: keyof ReactHTML,
props?: ClassAttributes<T> & P | null,
...children: ReactNode[]
): DetailedReactHTMLElement<P, T>;
function createElement<P extends SVGAttributes<T>, T extends SVGElement>(
type: keyof ReactSVG,
props?: ClassAttributes<T> & P | null,
...children: ReactNode[]
): ReactSVGElement;
function createElement<P extends DOMAttributes<T>, T extends Element>(
type: string,
props?: ClassAttributes<T> & P | null,
...children: ReactNode[]
): DOMElement<P, T>;
// Custom components
function createElement<P extends {}>(
type: FunctionComponent<P>,
props?: Attributes & P | null,
...children: ReactNode[]
): FunctionComponentElement<P>;
function createElement<P extends {}>(
type: ClassType<P, ClassicComponent<P, ComponentState>, ClassicComponentClass<P>>,
props?: ClassAttributes<ClassicComponent<P, ComponentState>> & P | null,
...children: ReactNode[]
): CElement<P, ClassicComponent<P, ComponentState>>;
function createElement<P extends {}, T extends Component<P, ComponentState>, C extends ComponentClass<P>>(
type: ClassType<P, T, C>,
props?: ClassAttributes<T> & P | null,
...children: ReactNode[]
): CElement<P, T>;
function createElement<P extends {}>(
type: FunctionComponent<P> | ComponentClass<P> | string,
props?: Attributes & P | null,
...children: ReactNode[]
): ReactElement<P>;
// DOM Elements
// ReactHTMLElement
function cloneElement<P extends HTMLAttributes<T>, T extends HTMLElement>(
element: DetailedReactHTMLElement<P, T>,
props?: P,
...children: ReactNode[]
): DetailedReactHTMLElement<P, T>;
// ReactHTMLElement, less specific
function cloneElement<P extends HTMLAttributes<T>, T extends HTMLElement>(
element: ReactHTMLElement<T>,
props?: P,
...children: ReactNode[]
): ReactHTMLElement<T>;
// SVGElement
function cloneElement<P extends SVGAttributes<T>, 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<P extends DOMAttributes<T>, T extends Element>(
element: DOMElement<P, T>,
props?: DOMAttributes<T> & P,
...children: ReactNode[]
): DOMElement<P, T>;
// Custom components
function cloneElement<P>(
element: FunctionComponentElement<P>,
props?: Partial<P> & Attributes,
...children: ReactNode[]
): FunctionComponentElement<P>;
function cloneElement<P, T extends Component<P, ComponentState>>(
element: CElement<P, T>,
props?: Partial<P> & ClassAttributes<T>,
...children: ReactNode[]
): CElement<P, T>;
function cloneElement<P>(
element: ReactElement<P>,
props?: Partial<P> & Attributes,
...children: ReactNode[]
): ReactElement<P>;
// Context via RenderProps
interface ProviderProps<T> {
value: T;
children?: ReactNode | undefined;
}
interface ConsumerProps<T> {
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<P = {}> {
/**
* **NOTE**: Exotic components are not callable.
*/
(props: P): ReactNode;
readonly $$typeof: symbol;
}
interface NamedExoticComponent<P = {}> extends ExoticComponent<P> {
displayName?: string | undefined;
}
interface ProviderExoticComponent<P> extends ExoticComponent<P> {
propTypes?: WeakValidationMap<P> | undefined;
}
type ContextType<C extends Context<any>> = C extends Context<infer T> ? 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<T> = ProviderExoticComponent<ProviderProps<T>>;
type Consumer<T> = ExoticComponent<ConsumerProps<T>>;
interface Context<T> {
Provider: Provider<T>;
Consumer: Consumer<T>;
displayName?: string | undefined;
}
function createContext<T>(
// If you thought this should be optional, see
// https://github.com/DefinitelyTyped/DefinitelyTyped/pull/24509#issuecomment-382213106
defaultValue: T,
): Context<T>;
function isValidElement<P>(object: {} | null | undefined): object is ReactElement<P>;
// Sync with `ReactChildren` until `ReactChildren` is removed.
const Children: {
map<T, C>(
children: C | ReadonlyArray<C>,
fn: (child: C, index: number) => T,
): C extends null | undefined ? C : Array<Exclude<T, boolean | null | undefined>>;
forEach<C>(children: C | ReadonlyArray<C>, fn: (child: C, index: number) => void): void;
count(children: any): number;
only<C>(children: C): C extends any[] ? never : C;
toArray(children: ReactNode | ReactNode[]): Array<Exclude<ReactNode, boolean | null | undefined>>;
};
const Fragment: ExoticComponent<{ children?: ReactNode | undefined }>;
const StrictMode: ExoticComponent<{ children?: ReactNode | undefined }>;
interface SuspenseProps {
children?: ReactNode | undefined;
/** A fallback react tree to show when a Suspense child (like React.lazy) suspends */
fallback?: ReactNode;
}
const Suspense: ExoticComponent<SuspenseProps>;
const version: string;
/**
* {@link https://react.dev/reference/react/Profiler#onrender-callback Profiler API}
*/
type ProfilerOnRenderCallback = (
id: string,
phase: "mount" | "update",
actualDuration: number,
baseDuration: number,
startTime: number,
commitTime: number,
interactions: Set<SchedulerInteraction>,
) => void;
interface ProfilerProps {
children?: ReactNode | undefined;
id: string;
onRender: ProfilerOnRenderCallback;
}
const Profiler: ExoticComponent<ProfilerProps>;
//
// Component API
// ----------------------------------------------------------------------
type ReactInstance = Component<any> | Element;
// Base component for plain JS classes
interface Component<P = {}, S = {}, SS = any> extends ComponentLifecycle<P, S, SS> {}
class Component<P, S> {
// 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<MyContext>(0)
*
* class Foo extends React.Component {
* static contextType = Ctx
* context!: React.ContextType<typeof Ctx>
* render () {
* return <>My context's value: {this.context}</>;
* }
* }
* ```
*
* @see https://react.dev/reference/react/Component#static-contexttype
*/
static contextType?: Context<any> | 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<typeof MyContext>
* // For TS 3.7 and above:
* declare context: React.ContextType<typeof MyContext>
* ```
*
* @see https://react.dev/reference/react/Component#context
*/
context: unknown;
constructor(props: Readonly<P> | P);
/**
* @deprecated
* @see https://legacy.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<K extends keyof S>(
state: ((prevState: Readonly<S>, props: Readonly<P>) => Pick<S, K> | S | null) | (Pick<S, K> | S | null),
callback?: () => void,
): void;
forceUpdate(callback?: () => void): void;
render(): ReactNode;
readonly props: Readonly<P>;
state: Readonly<S>;
/**
* @deprecated
* https://legacy.reactjs.org/docs/refs-and-the-dom.html#legacy-api-string-refs
*/
refs: {
[key: string]: ReactInstance;
};
}
class PureComponent<P = {}, S = {}, SS = any> extends Component<P, S, SS> {}
interface ClassicComponent<P = {}, S = {}> extends Component<P, S> {
replaceState(nextState: S, callback?: () => void): void;
isMounted(): boolean;
getInitialState?(): S;
}
interface ChildContextProvider<CC> {
getChildContext(): CC;
}
//
// Class Interfaces
// ----------------------------------------------------------------------
type FC<P = {}> = FunctionComponent<P>;
interface FunctionComponent<P = {}> {
(props: P, context?: any): ReactNode;
propTypes?: WeakValidationMap<P> | undefined;
contextTypes?: ValidationMap<any> | undefined;
defaultProps?: Partial<P> | undefined;
displayName?: string | undefined;
}
/**
* @deprecated - Equivalent with `React.FC`.
*/
type VFC<P = {}> = VoidFunctionComponent<P>;
/**
* @deprecated - Equivalent with `React.FunctionComponent`.
*/
interface VoidFunctionComponent<P = {}> {
(props: P, context?: any): ReactNode;
propTypes?: WeakValidationMap<P> | undefined;
contextTypes?: ValidationMap<any> | undefined;
defaultProps?: Partial<P> | undefined;
displayName?: string | undefined;
}
type ForwardedRef<T> = ((instance: T | null) => void) | MutableRefObject<T | null> | null;
interface ForwardRefRenderFunction<T, P = {}> {
(props: P, ref: ForwardedRef<T>): ReactNode;
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;
}
interface ComponentClass<P = {}, S = ComponentState> extends StaticLifecycle<P, S> {
new(props: P, context?: any): Component<P, S>;
propTypes?: WeakValidationMap<P> | undefined;
contextType?: Context<any> | undefined;
contextTypes?: ValidationMap<any> | undefined;
childContextTypes?: ValidationMap<any> | undefined;
defaultProps?: Partial<P> | undefined;
displayName?: string | undefined;
}
interface ClassicComponentClass<P = {}> extends ComponentClass<P> {
new(props: P, context?: any): ClassicComponent<P, ComponentState>;
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<P, T extends Component<P, ComponentState>, C extends ComponentClass<P>> =
& C
& (new(props: P, context?: any) => T);
//
// Component Specs and Lifecycle
// ----------------------------------------------------------------------
// This should actually be something like `Lifecycle<P, S> | DeprecatedLifecycle<P, S>`,
// as React will _not_ call the deprecated lifecycle methods if any of the new lifecycle
// methods are present.
interface ComponentLifecycle<P, S, SS = any> extends NewLifecycle<P, S, SS>, DeprecatedLifecycle<P, S> {
/**
* 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<P>, nextState: Readonly<S>, 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<P, S> {
getDerivedStateFromProps?: GetDerivedStateFromProps<P, S> | undefined;
getDerivedStateFromError?: GetDerivedStateFromError<P, S> | undefined;
}
type GetDerivedStateFromProps<P, S> =
/**
* 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<P>, prevState: S) => Partial<S> | null;
type GetDerivedStateFromError<P, S> =
/**
* 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<S> | null;
// This should be "infer SS" but can't use it yet
interface NewLifecycle<P, S, SS> {
/**
* 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<P>, prevState: Readonly<S>): 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<P>, prevState: Readonly<S>, snapshot?: SS): void;
}
interface DeprecatedLifecycle<P, S> {
/**
* 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://legacy.reactjs.org/blog/2018/03/27/update-on-async-rendering.html#initializing-state
* @see https://legacy.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://legacy.reactjs.org/blog/2018/03/27/update-on-async-rendering.html#initializing-state
* @see https://legacy.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://legacy.reactjs.org/blog/2018/03/27/update-on-async-rendering.html#updating-state-based-on-props
* @see https://legacy.reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path
*/
componentWillReceiveProps?(nextProps: Readonly<P>, 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://legacy.reactjs.org/blog/2018/03/27/update-on-async-rendering.html#updating-state-based-on-props
* @see https://legacy.reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path
*/
UNSAFE_componentWillReceiveProps?(nextProps: Readonly<P>, 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://legacy.reactjs.org/blog/2018/03/27/update-on-async-rendering.html#reading-dom-properties-before-an-update
* @see https://legacy.reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path
*/
componentWillUpdate?(nextProps: Readonly<P>, nextState: Readonly<S>, 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://legacy.reactjs.org/blog/2018/03/27/update-on-async-rendering.html#reading-dom-properties-before-an-update
* @see https://legacy.reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path
*/
UNSAFE_componentWillUpdate?(nextProps: Readonly<P>, nextState: Readonly<S>, nextContext: any): void;
}
interface Mixin<P, S> extends ComponentLifecycle<P, S> {
mixins?: Array<Mixin<P, S>> | undefined;
statics?: {
[key: string]: any;
} | undefined;
displayName?: string | undefined;
propTypes?: ValidationMap<any> | undefined;
contextTypes?: ValidationMap<any> | undefined;
childContextTypes?: ValidationMap<any> | undefined;
getDefaultProps?(): P;
getInitialState?(): S;
}
interface ComponentSpec<P, S> extends Mixin<P, S> {
render(): ReactNode;
[propertyName: string]: any;
}
function createRef<T>(): RefObject<T>;
// will show `ForwardRef(${Component.displayName || Component.name})` in devtools by default,
// but can be given its own specific name
interface ForwardRefExoticComponent<P> extends NamedExoticComponent<P> {
defaultProps?: Partial<P> | undefined;
propTypes?: WeakValidationMap<P> | undefined;
}
function forwardRef<T, P = {}>(
render: ForwardRefRenderFunction<T, P>,
): ForwardRefExoticComponent<PropsWithoutRef<P> & RefAttributes<T>>;
/** Ensures that the props do not include ref at all */
type PropsWithoutRef<P> =
// Omit 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 ? Omit<P, "ref"> : P) : P;
/** Ensures that the props do not include string ref, which cannot be forwarded */
type PropsWithRef<P> =
// 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<P> & { ref?: Exclude<R, string> | undefined }
: P
: P
: P;
type PropsWithChildren<P = unknown> = P & { children?: ReactNode | undefined };
/**
* NOTE: prefer ComponentPropsWithRef, if the ref is forwarded,
* or ComponentPropsWithoutRef when refs are not supported.
*/
type ComponentProps<T extends keyof JSX.IntrinsicElements | JSXElementConstructor<any>> = T extends
JSXElementConstructor<infer P> ? P
: T extends keyof JSX.IntrinsicElements ? JSX.IntrinsicElements[T]
: {};
type ComponentPropsWithRef<T extends ElementType> = T extends (new(props: infer P) => Component<any, any>)
? PropsWithoutRef<P> & RefAttributes<InstanceType<T>>
: PropsWithRef<ComponentProps<T>>;
type ComponentPropsWithoutRef<T extends ElementType> = PropsWithoutRef<ComponentProps<T>>;
type ComponentRef<T extends ElementType> = T extends NamedExoticComponent<
ComponentPropsWithoutRef<T> & RefAttributes<infer Method>
> ? Method
: ComponentPropsWithRef<T> extends RefAttributes<infer Method> ? Method
: never;
// will show `Memo(${Component.displayName || Component.name})` in devtools by default,
// but can be given its own specific name
type MemoExoticComponent<T extends ComponentType<any>> = NamedExoticComponent<ComponentPropsWithRef<T>> & {
readonly type: T;
};
function memo<P extends object>(
Component: FunctionComponent<P>,
propsAreEqual?: (prevProps: Readonly<P>, nextProps: Readonly<P>) => boolean,
): NamedExoticComponent<P>;
function memo<T extends ComponentType<any>>(
Component: T,
propsAreEqual?: (prevProps: Readonly<ComponentProps<T>>, nextProps: Readonly<ComponentProps<T>>) => boolean,
): MemoExoticComponent<T>;
type LazyExoticComponent<T extends ComponentType<any>> = ExoticComponent<ComponentPropsWithRef<T>> & {
readonly _result: T;
};
function lazy<T extends ComponentType<any>>(
factory: () => Promise<{ default: T }>,
): LazyExoticComponent<T>;
//
// 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> = 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<A> = (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<S, A> = (prevState: S, action: A) => S;
// If useReducer accepts a reducer without action, dispatch may be called without any parameters.
type ReducerWithoutAction<S> = (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<any, any>> = R extends Reducer<infer S, any> ? S : never;
type ReducerAction<R extends Reducer<any, any>> = R extends Reducer<any, infer A> ? A : never;
// The identity check is done with the SameValue algorithm (Object.is), which is stricter than ===
type ReducerStateWithoutAction<R extends ReducerWithoutAction<any>> = R extends ReducerWithoutAction<infer S> ? S
: never;
type DependencyList = ReadonlyArray<unknown>;
// NOTE: callbacks are _only_ allowed to return either void, or a destructor.
type EffectCallback = () => void | Destructor;
interface MutableRefObject<T> {
current: T;
}
// This will technically work if you give a Consumer<T> or Provider<T> 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://react.dev/reference/react/useContext
*/
function useContext<T>(context: Context<T> /*, (not public API) observedBits?: number|boolean */): T;
/**
* Returns a stateful value, and a function to update it.
*
* @version 16.8.0
* @see https://react.dev/reference/react/useState
*/
function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>];
// convenience overload when first argument is omitted
/**
* Returns a stateful value, and a function to update it.
*
* @version 16.8.0
* @see https://react.dev/reference/react/useState
*/
function useState<S = undefined>(): [S | undefined, Dispatch<SetStateAction<S | undefined>>];
/**
* 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://react.dev/reference/react/useReducer
*/
// overload where dispatch could accept 0 arguments.
function useReducer<R extends ReducerWithoutAction<any>, I>(
reducer: R,
initializerArg: I,
initializer: (arg: I) => ReducerStateWithoutAction<R>,
): [ReducerStateWithoutAction<R>, 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://react.dev/reference/react/useReducer
*/
// overload where dispatch could accept 0 arguments.
function useReducer<R extends ReducerWithoutAction<any>>(
reducer: R,
initializerArg: ReducerStateWithoutAction<R>,
initializer?: undefined,
): [ReducerStateWithoutAction<R>, 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://react.dev/reference/react/useReducer
*/
// overload where "I" may be a subset of ReducerState<R>; used to provide autocompletion.
// If "I" matches ReducerState<R> 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<R extends Reducer<any, any>, I>(
reducer: R,
initializerArg: I & ReducerState<R>,
initializer: (arg: I & ReducerState<R>) => ReducerState<R>,
): [ReducerState<R>, Dispatch<ReducerAction<R>>];
/**
* 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://react.dev/reference/react/useReducer
*/
// overload for free "I"; all goes as long as initializer converts it into "ReducerState<R>".
function useReducer<R extends Reducer<any, any>, I>(
reducer: R,
initializerArg: I,
initializer: (arg: I) => ReducerState<R>,
): [ReducerState<R>, Dispatch<ReducerAction<R>>];
/**
* 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://react.dev/reference/react/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<R extends Reducer<any, any>>(
reducer: R,
initialState: ReducerState<R>,
initializer?: undefined,
): [ReducerState<R>, Dispatch<ReducerAction<R>>];
/**
* `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://react.dev/reference/react/useRef
*/
function useRef<T>(initialValue: T): MutableRefObject<T>;
// 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://react.dev/reference/react/useRef
*/
function useRef<T>(initialValue: T | null): RefObject<T>;
// 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://react.dev/reference/react/useRef
*/
function useRef<T = undefined>(): MutableRefObject<T | undefined>;
/**
* 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://react.dev/reference/react/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://react.dev/reference/react/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<T>
/**
* `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://react.dev/reference/react/useImperativeHandle
*/
function useImperativeHandle<T, R extends T>(ref: Ref<T> | 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://react.dev/reference/react/useCallback
*/
// A specific function type would not trigger implicit any.
// See https://github.com/DefinitelyTyped/DefinitelyTyped/issues/52873#issuecomment-845806435 for a comparison between `Function` and more specific types.
// tslint:disable-next-line ban-types
function useCallback<T extends Function>(callback: T, deps: DependencyList): T;
/**
* `useMemo` will only recompute the memoized value when one of the `deps` has changed.
*
* @version 16.8.0
* @see https://react.dev/reference/react/useMemo
*/
// allow undefined, but don't make it optional as that is very likely a mistake
function useMemo<T>(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://react.dev/reference/react/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.