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;