Package Exports
- forward-ref-as
- forward-ref-as/package.json
Readme
forwardRefAs()
A wrapper aroundReact.forwardRef()that allows HTML attributes and prop types to be inferred from anasprop.
npm i forward-ref-as
Quick start
import forwardRefAs from 'forward-ref-as'
import type {AsProp} from 'forward-ref-as'
// Forwards `ref` to the underlying button and adds strong
// types for the `as` prop.
const Button = forwardRefAs<ButtonProps, 'button'>(
({as: As = 'button', ...props}, ref) => <As ref={ref} {...props} />
)
interface ButtonProps {
as?: AsProp
}
// ✅ Will pass type checking and autocomplete correctly
<Button as='a' href='https://jaredLunde.com'/>
// ❌ Will fail type checking and not autocomplete "href"
<Button href='#'>API
forwardRefAs()
A wrapper around React.forwardRef() with the same call signature, but
a type signature that allows as prop HTML attributes and React prop types
to be inferred.
function forwardRefAs<Props, DefaultAs extends AsProp = 'div'>(
render: React.RefForwardingComponent<
DefaultAs extends keyof JSX.IntrinsicElements
? FromReactType<DefaultAs>
: DefaultAs,
Props
>
): ForwardRefAsExoticComponent<Props, DefaultAs>Types
AsProp
/**
* These are the types accepted by an "as" prop
*/
export type AsProp = React.ReactType | keyof JSX.IntrinsicElementsForwardRefAsExoticComponent
/**
* This is a signature that matches `ForwardRefExoticComponent`, but allows for
* inheriting attributes via the "as" prop and gets rid of `propTypes` because,
* dang it, this is TypeScript! Get that outta here.
*/
export type ForwardRefAsExoticComponent<Props, DefaultAs extends AsProp> = Pick<
React.ForwardRefExoticComponent<DefaultAs>,
Exclude<keyof React.ForwardRefExoticComponent<DefaultAs>, 'defaultProps'>
> & {
<As extends AsProp = DefaultAs>(
props: Prefer<{as?: As} & Props, React.ComponentProps<As>> &
React.RefAttributes<
As extends keyof JSX.IntrinsicElements ? FromReactType<As> : As
>
): JSX.Element | null
defaultProps: {
as?: AsProp
} & Partial<Props> &
Partial<React.ComponentPropsWithoutRef<DefaultAs>>
displayName: string
}PropsOf
/**
* Extracts the props of a component type
* Credit: Emotion
*/
export type PropsOf<
E extends keyof JSX.IntrinsicElements | React.JSXElementConstructor<any>
> = JSX.LibraryManagedAttributes<E, React.ComponentPropsWithRef<E>>FromReactType
/**
* Maps a keyof JSX.IntrinsicElement (e.g. 'div' or 'svg') or a
* React.ComponentType to it's type.
*
* For example:
* FromReactType<"div"> ==> HTMLDivElement
* FromReactType<"svg"> ==> SVGSVGElement
* FromReactType<React.FC<P>. ==> React.FC<P>
*/
export type FromReactType<
T extends React.ReactType
> = T extends keyof JSX.IntrinsicElements
? JSX.IntrinsicElements[T] extends React.DetailedHTMLFactory<
React.HTMLAttributes<infer U>,
infer U
>
? U
: JSX.IntrinsicElements[T] extends React.SVGProps<infer V>
? V
: never
: TPrefer
/**
* Omits an props in `T` that are already present in `P`
*/
export type Prefer<P, T> = P & Omit<T, keyof P>LICENSE
MIT