Skip to content

Instantly share code, notes, and snippets.

@dfee
Last active January 18, 2019 23:01
Show Gist options
  • Save dfee/cf657ca93b050734b839b12ec20d5fb9 to your computer and use it in GitHub Desktop.
Save dfee/cf657ca93b050734b839b12ec20d5fb9 to your computer and use it in GitHub Desktop.
map React.ReactType -> ElementType -> React.ReactType
/**
* type MyType = "table" // a keyof JSX.IntrinsicElements
* type MyTypeElementType = ElementTypeFromReactType<MyType>; // => HTMLTableElement
* type MyType2 = ReactTypeFromElementType<MyTypeElementType>; // => "table"
**/
import * as React from 'react';
/**
* Map a React.ReactType "T" to it's real type:
* a keyof JSX.IntrinsicElements ==> the specific HTMLElemnt or SVGElement
* a React.ComponentType<any> ==> the Function, or Class Component signature
*
* For example:
* ElementTypeFromReactType<"div"> ==> HTMLDivElement
* ElementTypeFromReactType<"svg"> ==> SVGSVGElement
* ElementTypeFromReactType<"circle"> ==> SVGCircleElement
* ElementTypeFromReactType<React.FC<P>> ==> React.FC<P>
*/
export type ElementTypeFromReactType<
T extends React.ReactType
> = T extends keyof JSX.IntrinsicElements
? JSX.IntrinsicElements[T] extends React.DetailedHTMLProps<
React.HTMLAttributes<infer U>,
infer U
>
? U
: JSX.IntrinsicElements[T] extends React.SVGProps<infer V>
? V
: never
: T;
/**
* Map an HTMLElement, SVGElement, or ComponentType "T" to it's React.ReactType
* (i.e. for React.createElement or React.createRef)
*
* For example:
* ReactTypeFromElementType<HTMLDivElement> ==> "div" (or anything that shares its interface)
* ReactTypeFromElementType<SVGSVGElement> ==> "svg"
* ReactTypeFromElementType<SVGCircleElement> ==> "circle"
* ReactTypeFromElementType<React.FC<P>> ==> React.FC<P>
*/
export type AllowedNames<Base, Condition> = {
[K in keyof Base]: Base[K] extends Condition ? K : never
}[keyof Base];
export type SimpleJSXIntrinsicElementMapping = {
[K in keyof JSX.IntrinsicElements]: JSX.IntrinsicElements[K] extends React.DetailedHTMLProps<
React.HTMLAttributes<infer U>,
infer U
>
? U
: JSX.IntrinsicElements[K] extends React.SVGProps<infer V>
? V
: never
};
export type ReactTypeFromElementType<
T extends React.ComponentType | HTMLElement | SVGElement
> = T extends HTMLElement | SVGElement
? AllowedNames<SimpleJSXIntrinsicElementMapping, T>
: T;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment