-
Notifications
You must be signed in to change notification settings - Fork 930
/
Copy pathpolymorphic.ts
62 lines (53 loc) · 2.36 KB
/
polymorphic.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import * as React from 'react';
/* -------------------------------------------------------------------------------------------------
* Utility types
* -----------------------------------------------------------------------------------------------*/
type Merge<P1 = {}, P2 = {}> = Omit<P1, keyof P2> & P2;
type MergeProps<E, P = {}> = P &
Merge<E extends React.ElementType ? React.ComponentPropsWithRef<E> : never, P>;
/**
* Infers the OwnProps if E is a ForwardRefExoticComponentWithAs
*/
type OwnProps<E> = E extends ForwardRefComponent<any, infer P> ? P : {};
/**
* Infers the JSX.IntrinsicElement if E is a ForwardRefExoticComponentWithAs
*/
type IntrinsicElement<E> = E extends ForwardRefComponent<infer I, any> ? I : never;
type NarrowIntrinsic<E> = E extends keyof JSX.IntrinsicElements ? E : never;
/* -------------------------------------------------------------------------------------------------
* ForwardRefComponent
* -----------------------------------------------------------------------------------------------*/
interface ForwardRefComponent<
IntrinsicElementString,
OwnProps = {}
/**
* Extends original type to ensure built in React types play nice
* with polymorphic components still e.g. `React.ElementRef` etc.
*/
> extends React.ForwardRefExoticComponent<
MergeProps<IntrinsicElementString, OwnProps & { as?: IntrinsicElementString }>
> {
/**
* When passing an `as` prop as a string, use this overload.
* Merges original own props (without DOM props) and the inferred props
* from `as` element with the own props taking precendence.
*
* We explicitly define a `JSX.IntrinsicElements` overload so that
* events are typed for consumers.
*/
<As extends keyof JSX.IntrinsicElements = NarrowIntrinsic<IntrinsicElementString>>(
props: MergeProps<As, OwnProps & { as: As }>
): React.ReactElement | null;
/**
* When passing an `as` prop as a component, use this overload.
* Merges original own props (without DOM props) and the inferred props
* from `as` element with the own props taking precendence.
*
* We don't use `React.ComponentType` here as we get type errors
* when consumers try to do inline `as` components.
*/
<As extends React.ElementType>(
props: MergeProps<As, OwnProps & { as: As }>
): React.ReactElement | null;
}
export type { ForwardRefComponent, OwnProps, IntrinsicElement, Merge };