diff --git a/compat/src/index.d.ts b/compat/src/index.d.ts index 9405f7d99a..504ca40d53 100644 --- a/compat/src/index.d.ts +++ b/compat/src/index.d.ts @@ -83,10 +83,13 @@ declare namespace React { isPureReactComponent: boolean; } - export function memo

( - component: preact.FunctionalComponent

, - comparer?: (prev: P, next: P) => boolean - ): preact.FunctionComponent

; + export function memo>( + component: C, + comparer?: ( + prev: preact.ComponentProps, + next: preact.ComponentProps + ) => boolean + ): C; export interface ForwardFn

{ (props: P, ref: Ref): preact.ComponentChild; diff --git a/compat/test/ts/memo.tsx b/compat/test/ts/memo.tsx new file mode 100644 index 0000000000..a6bbbb8d91 --- /dev/null +++ b/compat/test/ts/memo.tsx @@ -0,0 +1,40 @@ +import * as React from '../../src'; + +function ExpectType(v: T) {} // type assertion helper + +interface MemoProps { + required: string; + optional?: string; + defaulted: string; +} + +const ReadonlyBaseComponent = (props: Readonly) => ( +

{props.required + props.optional + props.defaulted}
+); +ReadonlyBaseComponent.defaultProps = { defaulted: '' }; + +const BaseComponent = (props: MemoProps) => ( +
{props.required + props.optional + props.defaulted}
+); +BaseComponent.defaultProps = { defaulted: '' }; + +// memo for readonly component with default comparison +const MemoedReadonlyComponent = React.memo(ReadonlyBaseComponent); +ExpectType>(MemoedReadonlyComponent); +export const memoedReadonlyComponent = ( + +); + +// memo for non-readonly component with default comparison +const MemoedComponent = React.memo(BaseComponent); +ExpectType>(MemoedComponent); +export const memoedComponent = ; + +// memo with custom comparison +const CustomMemoedComponent = React.memo(BaseComponent, (a, b) => { + ExpectType(a); + ExpectType(b); + return a.required === b.required; +}); +ExpectType>(CustomMemoedComponent); +export const customMemoedComponent = ; diff --git a/src/index.d.ts b/src/index.d.ts index 5d3807d2cd..8cfc68a836 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -69,13 +69,18 @@ declare namespace preact { }; } - type RenderableProps = Readonly< - P & Attributes & { children?: ComponentChildren; ref?: Ref } - >; + type RenderableProps = P & + Readonly }>; type ComponentType

= ComponentClass

| FunctionComponent

; type ComponentFactory

= ComponentType

; + type ComponentProps> = C extends ComponentType< + infer P + > + ? P + : never; + interface FunctionComponent

{ (props: RenderableProps

, context?: any): VNode | null; displayName?: string;