Skip to content

Instantly share code, notes, and snippets.

@kripod
Last active February 6, 2025 07:44
Show Gist options
  • Select an option

  • Save kripod/4434e7cecfdecee160026aee49ea6ee8 to your computer and use it in GitHub Desktop.

Select an option

Save kripod/4434e7cecfdecee160026aee49ea6ee8 to your computer and use it in GitHub Desktop.

Revisions

  1. kripod revised this gist Mar 22, 2024. No changes.
  2. kripod revised this gist Feb 12, 2020. 1 changed file with 7 additions and 13 deletions.
    20 changes: 7 additions & 13 deletions Box.tsx
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    import React from 'react';

    // Source: https://github.com/emotion-js/emotion/blob/master/packages/styled-base/types/helper.d.ts
    export type PropsOf<
    type PropsOf<
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    E extends keyof JSX.IntrinsicElements | React.JSXElementConstructor<any>
    > = JSX.LibraryManagedAttributes<E, React.ComponentPropsWithRef<E>>;
    @@ -16,22 +16,16 @@ export type BoxProps<E extends React.ElementType> = BoxOwnProps<E> &
    export type PolymorphicComponentProps<E extends React.ElementType, P> = P &
    BoxProps<E>;

    const defaultElement = 'div';

    export const Box = React.forwardRef(
    ({ as, ...restProps }: BoxOwnProps, ref: React.Ref<Element>) => {
    const Element = as || 'div';
    const Element = as || defaultElement;
    return <Element ref={ref} {...restProps} />;
    },
    ) as <E extends React.ElementType = 'div'>(props: BoxProps<E>) => JSX.Element;

    /*
    export function BoxWithoutRef<E extends React.ElementType = 'div'>({
    as,
    ...restProps
    }: React.PropsWithoutRef<BoxProps<E>>): JSX.Element {
    const Element = as || 'div';
    return <Element {...restProps} />;
    }
    */
    ) as <E extends React.ElementType = typeof defaultElement>(
    props: BoxProps<E>,
    ) => JSX.Element;

    /* Usage example: */

  3. kripod revised this gist Feb 12, 2020. 1 changed file with 20 additions and 0 deletions.
    20 changes: 20 additions & 0 deletions Box.tsx
    Original file line number Diff line number Diff line change
    @@ -13,6 +13,9 @@ export interface BoxOwnProps<E extends React.ElementType = React.ElementType> {
    export type BoxProps<E extends React.ElementType> = BoxOwnProps<E> &
    Omit<PropsOf<E>, keyof BoxOwnProps>;

    export type PolymorphicComponentProps<E extends React.ElementType, P> = P &
    BoxProps<E>;

    export const Box = React.forwardRef(
    ({ as, ...restProps }: BoxOwnProps, ref: React.Ref<Element>) => {
    const Element = as || 'div';
    @@ -29,3 +32,20 @@ export function BoxWithoutRef<E extends React.ElementType = 'div'>({
    return <Element {...restProps} />;
    }
    */

    /* Usage example: */

    interface CustomComponentOwnProps {
    customProp?: number;
    onClick: boolean;
    }

    type CustomComponentProps<
    E extends React.ElementType
    > = PolymorphicComponentProps<E, CustomComponentOwnProps>;

    function CustomComponent<E extends React.ElementType>(
    props: CustomComponentProps<E>,
    ): JSX.Element {
    return <Box {...props} />;
    }
  4. kripod revised this gist Feb 12, 2020. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions Box.tsx
    Original file line number Diff line number Diff line change
    @@ -20,10 +20,12 @@ export const Box = React.forwardRef(
    },
    ) as <E extends React.ElementType = 'div'>(props: BoxProps<E>) => JSX.Element;

    /*
    export function BoxWithoutRef<E extends React.ElementType = 'div'>({
    as,
    ...restProps
    }: React.PropsWithoutRef<BoxProps<E>>): JSX.Element {
    const Element = as || 'div';
    return <Element {...restProps} />;
    }
    */
  5. kripod revised this gist Feb 12, 2020. 1 changed file with 7 additions and 7 deletions.
    14 changes: 7 additions & 7 deletions Box.tsx
    Original file line number Diff line number Diff line change
    @@ -13,17 +13,17 @@ export interface BoxOwnProps<E extends React.ElementType = React.ElementType> {
    export type BoxProps<E extends React.ElementType> = BoxOwnProps<E> &
    Omit<PropsOf<E>, keyof BoxOwnProps>;

    export const Box = React.forwardRef(
    ({ as, ...restProps }: BoxOwnProps, ref: React.Ref<Element>) => {
    const Element = as || 'div';
    return <Element ref={ref} {...restProps} />;
    },
    ) as <E extends React.ElementType = 'div'>(props: BoxProps<E>) => JSX.Element;

    export function BoxWithoutRef<E extends React.ElementType = 'div'>({
    as,
    ...restProps
    }: React.PropsWithoutRef<BoxProps<E>>): JSX.Element {
    const Element = as || 'div';
    return <Element {...restProps} />;
    }

    export const Box = React.forwardRef(
    ({ as, ...restProps }: BoxOwnProps, ref: React.Ref<Element>) => {
    const Element = as || 'div';
    return <Element ref={ref} {...restProps} />;
    },
    ) as <E extends React.ElementType = 'div'>(props: BoxProps<E>) => JSX.Element;
  6. kripod revised this gist Feb 12, 2020. 1 changed file with 5 additions and 9 deletions.
    14 changes: 5 additions & 9 deletions Box.tsx
    Original file line number Diff line number Diff line change
    @@ -4,7 +4,7 @@ import React from 'react';
    export type PropsOf<
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    E extends keyof JSX.IntrinsicElements | React.JSXElementConstructor<any>
    > = JSX.LibraryManagedAttributes<E, React.ComponentPropsWithoutRef<E>>;
    > = JSX.LibraryManagedAttributes<E, React.ComponentPropsWithRef<E>>;

    export interface BoxOwnProps<E extends React.ElementType = React.ElementType> {
    as?: E;
    @@ -16,18 +16,14 @@ export type BoxProps<E extends React.ElementType> = BoxOwnProps<E> &
    export function BoxWithoutRef<E extends React.ElementType = 'div'>({
    as,
    ...restProps
    }: BoxProps<E>): JSX.Element {
    }: React.PropsWithoutRef<BoxProps<E>>): JSX.Element {
    const Element = as || 'div';
    return <Element {...restProps} />;
    }

    export const Box = React.forwardRef(
    (
    { as: Element = 'div', ...restProps }: BoxOwnProps,
    ref: React.Ref<Element>,
    ) => {
    ({ as, ...restProps }: BoxOwnProps, ref: React.Ref<Element>) => {
    const Element = as || 'div';
    return <Element ref={ref} {...restProps} />;
    },
    ) as <E extends React.ElementType = 'div', T = Element>(
    props: BoxProps<E> & React.RefAttributes<T>,
    ) => JSX.Element;
    ) as <E extends React.ElementType = 'div'>(props: BoxProps<E>) => JSX.Element;
  7. kripod revised this gist Feb 12, 2020. 1 changed file with 11 additions and 14 deletions.
    25 changes: 11 additions & 14 deletions Box.tsx
    Original file line number Diff line number Diff line change
    @@ -3,24 +3,21 @@ import React from 'react';
    // Source: https://github.com/emotion-js/emotion/blob/master/packages/styled-base/types/helper.d.ts
    export type PropsOf<
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    C extends keyof JSX.IntrinsicElements | React.JSXElementConstructor<any>
    > = JSX.LibraryManagedAttributes<C, React.ComponentPropsWithoutRef<C>>;
    E extends keyof JSX.IntrinsicElements | React.JSXElementConstructor<any>
    > = JSX.LibraryManagedAttributes<E, React.ComponentPropsWithoutRef<E>>;

    export interface BoxOwnProps<C extends React.ElementType = React.ElementType> {
    as?: C;
    export interface BoxOwnProps<E extends React.ElementType = React.ElementType> {
    as?: E;
    }

    export type BoxProps<C extends React.ElementType> = BoxOwnProps<C> & PropsOf<C>;
    export type BoxProps<E extends React.ElementType> = BoxOwnProps<E> &
    Omit<PropsOf<E>, keyof BoxOwnProps>;

    type AsProp<C> =
    | keyof JSX.IntrinsicElements
    | React.ComponentType<C extends React.ComponentType<infer P> ? P : never>;

    export function BoxWithoutRef<C extends AsProp<C> = 'div'>({
    export function BoxWithoutRef<E extends React.ElementType = 'div'>({
    as,
    ...restProps
    }: BoxProps<C>): JSX.Element {
    const Element: React.ElementType = as || 'div';
    }: BoxProps<E>): JSX.Element {
    const Element = as || 'div';
    return <Element {...restProps} />;
    }

    @@ -31,6 +28,6 @@ export const Box = React.forwardRef(
    ) => {
    return <Element ref={ref} {...restProps} />;
    },
    ) as <T, C extends AsProp<C> = 'div'>(
    props: BoxProps<C> & React.RefAttributes<T>,
    ) as <E extends React.ElementType = 'div', T = Element>(
    props: BoxProps<E> & React.RefAttributes<T>,
    ) => JSX.Element;
  8. kripod revised this gist Feb 12, 2020. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion Box.tsx
    Original file line number Diff line number Diff line change
    @@ -31,4 +31,6 @@ export const Box = React.forwardRef(
    ) => {
    return <Element ref={ref} {...restProps} />;
    },
    ) as <C extends AsProp<C> = 'div'>(props: BoxProps<C>) => JSX.Element;
    ) as <T, C extends AsProp<C> = 'div'>(
    props: BoxProps<C> & React.RefAttributes<T>,
    ) => JSX.Element;
  9. kripod revised this gist Feb 12, 2020. 1 changed file with 9 additions and 16 deletions.
    25 changes: 9 additions & 16 deletions Box.tsx
    Original file line number Diff line number Diff line change
    @@ -12,13 +12,14 @@ export interface BoxOwnProps<C extends React.ElementType = React.ElementType> {

    export type BoxProps<C extends React.ElementType> = BoxOwnProps<C> & PropsOf<C>;

    export function BoxWithoutRef<
    C extends
    | keyof JSX.IntrinsicElements
    | React.ComponentType<
    C extends React.ComponentType<infer P> ? P : never
    > = 'div'
    >({ as, ...restProps }: BoxProps<C>): JSX.Element {
    type AsProp<C> =
    | keyof JSX.IntrinsicElements
    | React.ComponentType<C extends React.ComponentType<infer P> ? P : never>;

    export function BoxWithoutRef<C extends AsProp<C> = 'div'>({
    as,
    ...restProps
    }: BoxProps<C>): JSX.Element {
    const Element: React.ElementType = as || 'div';
    return <Element {...restProps} />;
    }
    @@ -30,12 +31,4 @@ export const Box = React.forwardRef(
    ) => {
    return <Element ref={ref} {...restProps} />;
    },
    ) as <
    C extends
    | keyof JSX.IntrinsicElements
    | React.ComponentType<
    C extends React.ComponentType<infer P> ? P : never
    > = 'div'
    >(
    props: BoxProps<C>,
    ) => JSX.Element;
    ) as <C extends AsProp<C> = 'div'>(props: BoxProps<C>) => JSX.Element;
  10. kripod revised this gist Feb 11, 2020. 1 changed file with 13 additions and 12 deletions.
    25 changes: 13 additions & 12 deletions Box.tsx
    Original file line number Diff line number Diff line change
    @@ -6,35 +6,36 @@ export type PropsOf<
    C extends keyof JSX.IntrinsicElements | React.JSXElementConstructor<any>
    > = JSX.LibraryManagedAttributes<C, React.ComponentPropsWithoutRef<C>>;

    export interface BoxProps<C extends React.ElementType = React.ElementType> {
    export interface BoxOwnProps<C extends React.ElementType = React.ElementType> {
    as?: C;
    }

    export type BoxProps<C extends React.ElementType> = BoxOwnProps<C> & PropsOf<C>;

    export function BoxWithoutRef<
    C extends
    | keyof JSX.IntrinsicElements
    | React.ComponentType<C extends React.ComponentType<infer P> ? P : never>
    >({ as, ...restProps }: BoxProps<C> & PropsOf<C>): JSX.Element {
    | React.ComponentType<
    C extends React.ComponentType<infer P> ? P : never
    > = 'div'
    >({ as, ...restProps }: BoxProps<C>): JSX.Element {
    const Element: React.ElementType = as || 'div';
    return <Element {...restProps} />;
    }

    export const Box = React.forwardRef(
    <
    C extends
    | keyof JSX.IntrinsicElements
    | React.ComponentType<C extends React.ComponentType<infer P> ? P : never>
    >(
    { as, ...restProps }: BoxProps<C> & PropsOf<C>,
    (
    { as: Element = 'div', ...restProps }: BoxOwnProps,
    ref: React.Ref<Element>,
    ) => {
    const Element: React.ElementType = as || 'div';
    return <Element ref={ref} {...restProps} />;
    },
    ) as <
    C extends
    | keyof JSX.IntrinsicElements
    | React.ComponentType<C extends React.ComponentType<infer P> ? P : never>
    | React.ComponentType<
    C extends React.ComponentType<infer P> ? P : never
    > = 'div'
    >(
    props: BoxProps<C> & PropsOf<C>,
    props: BoxProps<C>,
    ) => JSX.Element;
  11. kripod revised this gist Feb 11, 2020. 1 changed file with 21 additions and 1 deletion.
    22 changes: 21 additions & 1 deletion Box.tsx
    Original file line number Diff line number Diff line change
    @@ -10,11 +10,31 @@ export interface BoxProps<C extends React.ElementType = React.ElementType> {
    as?: C;
    }

    export function Box<
    export function BoxWithoutRef<
    C extends
    | keyof JSX.IntrinsicElements
    | React.ComponentType<C extends React.ComponentType<infer P> ? P : never>
    >({ as, ...restProps }: BoxProps<C> & PropsOf<C>): JSX.Element {
    const Element: React.ElementType = as || 'div';
    return <Element {...restProps} />;
    }

    export const Box = React.forwardRef(
    <
    C extends
    | keyof JSX.IntrinsicElements
    | React.ComponentType<C extends React.ComponentType<infer P> ? P : never>
    >(
    { as, ...restProps }: BoxProps<C> & PropsOf<C>,
    ref: React.Ref<Element>,
    ) => {
    const Element: React.ElementType = as || 'div';
    return <Element ref={ref} {...restProps} />;
    },
    ) as <
    C extends
    | keyof JSX.IntrinsicElements
    | React.ComponentType<C extends React.ComponentType<infer P> ? P : never>
    >(
    props: BoxProps<C> & PropsOf<C>,
    ) => JSX.Element;
  12. kripod revised this gist Feb 8, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Box.tsx
    Original file line number Diff line number Diff line change
    @@ -10,7 +10,7 @@ export interface BoxProps<C extends React.ElementType = React.ElementType> {
    as?: C;
    }

    export default function Box<
    export function Box<
    C extends
    | keyof JSX.IntrinsicElements
    | React.ComponentType<C extends React.ComponentType<infer P> ? P : never>
  13. kripod revised this gist Feb 8, 2020. 1 changed file with 6 additions and 12 deletions.
    18 changes: 6 additions & 12 deletions Box.tsx
    Original file line number Diff line number Diff line change
    @@ -1,26 +1,20 @@
    import React from 'react';

    // Source: https://github.com/typescript-cheatsheets/react-typescript-cheatsheet/blob/master/ADVANCED.md#extracting-prop-types-of-a-component
    type ApparentComponentProps<
    // Source: https://github.com/emotion-js/emotion/blob/master/packages/styled-base/types/helper.d.ts
    export type PropsOf<
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    C extends keyof JSX.IntrinsicElements | React.JSXElementConstructor<any>
    > = C extends React.JSXElementConstructor<infer P>
    ? JSX.LibraryManagedAttributes<C, P>
    : React.ComponentProps<C>;
    > = JSX.LibraryManagedAttributes<C, React.ComponentPropsWithoutRef<C>>;

    export interface BoxProps<C = React.ElementType> {
    export interface BoxProps<C extends React.ElementType = React.ElementType> {
    as?: C;
    }

    export function Box<
    export default function Box<
    C extends
    | keyof JSX.IntrinsicElements
    | React.ComponentType<C extends React.ComponentType<infer P> ? P : never>
    >({
    as,
    ...restProps
    }: BoxProps<C> &
    React.PropsWithoutRef<ApparentComponentProps<C>>): JSX.Element {
    >({ as, ...restProps }: BoxProps<C> & PropsOf<C>): JSX.Element {
    const Element: React.ElementType = as || 'div';
    return <Element {...restProps} />;
    }
  14. kripod created this gist Jan 28, 2020.
    26 changes: 26 additions & 0 deletions Box.tsx
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,26 @@
    import React from 'react';

    // Source: https://github.com/typescript-cheatsheets/react-typescript-cheatsheet/blob/master/ADVANCED.md#extracting-prop-types-of-a-component
    type ApparentComponentProps<
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    C extends keyof JSX.IntrinsicElements | React.JSXElementConstructor<any>
    > = C extends React.JSXElementConstructor<infer P>
    ? JSX.LibraryManagedAttributes<C, P>
    : React.ComponentProps<C>;

    export interface BoxProps<C = React.ElementType> {
    as?: C;
    }

    export function Box<
    C extends
    | keyof JSX.IntrinsicElements
    | React.ComponentType<C extends React.ComponentType<infer P> ? P : never>
    >({
    as,
    ...restProps
    }: BoxProps<C> &
    React.PropsWithoutRef<ApparentComponentProps<C>>): JSX.Element {
    const Element: React.ElementType = as || 'div';
    return <Element {...restProps} />;
    }