How to extract the all parameter type from a function overloading?

28 Views Asked by At

I try to extract the element parameter type from the ReactDOM.render() function.

import React from 'react'; // types: 17.0.2
import ReactDOM from 'react-dom'; // types: 16.9.0

const render = (element: Parameters<typeof ReactDOM.render>[0]) => {

}

render(<div />) // error

Got error:

Argument of type 'Element' is not assignable to parameter of type 'ReactElement<any, string | JSXElementConstructor<any>>[]'.
  Type 'Element' is missing the following properties from type 'ReactElement<any, string | JSXElementConstructor<any>>[]': length, pop, push, concat, and 26 more.(2345)

The TS type of ReactDOM.render() function from @types/react-dom/index.d.ts:

export const render: Renderer;

//...

export interface Renderer {
    // Deprecated(render): The return value is deprecated.
    // In future releases the render function's return type will be void.

    <T extends Element>(
        element: DOMElement<DOMAttributes<T>, T>,
        container: Container | null,
        callback?: () => void,
    ): T;

    (
        element: Array<DOMElement<DOMAttributes<any>, any>>,
        container: Container | null,
        callback?: () => void,
    ): Element;

    (
        element: SFCElement<any> | Array<SFCElement<any>>,
        container: Container | null,
        callback?: () => void,
    ): void;

    <P, T extends Component<P, ComponentState>>(
        element: CElement<P, T>,
        container: Container | null,
        callback?: () => void,
    ): T;

    (
        element: Array<CElement<any, Component<any, ComponentState>>>,
        container: Container | null,
        callback?: () => void,
    ): Component<any, ComponentState>;

    <P>(
        element: ReactElement<P>,
        container: Container | null,
        callback?: () => void,
        // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
    ): Component<P, ComponentState> | Element | void;

    (
        element: ReactElement[],
        container: Container | null,
        callback?: () => void,
        // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
    ): Component<any, ComponentState> | Element | void;
}

The expected type may be a union type composed of each type of element parameter, like:

type Element = DOMElement<DOMAttributes<T>, T> 
| Array<DOMElement<DOMAttributes<any>, any>> 
| SFCElement<any> 
| Array<SFCElement<any>>
| CElement<P, T>
| Array<CElement<any, Component<any, ComponentState>>>
| ReactElement<P>
| ReactElement[]

Is this possible for TypeScript?

TS Playground

0

There are 0 best solutions below