diff --git a/types/wordpress__compose/higher-order/if-condition/index.d.ts b/types/wordpress__compose/higher-order/if-condition/index.d.ts
new file mode 100644
index 0000000000..3e1adbca8e
--- /dev/null
+++ b/types/wordpress__compose/higher-order/if-condition/index.d.ts
@@ -0,0 +1,5 @@
+import { ComponentType, FC } from '@wordpress/element';
+
+declare function ifCondition
(predicate: (props: P) => boolean): (component: ComponentType
) => FC
;
+
+export default ifCondition;
diff --git a/types/wordpress__compose/higher-order/pure/index.d.ts b/types/wordpress__compose/higher-order/pure/index.d.ts
new file mode 100644
index 0000000000..4e2fc547e1
--- /dev/null
+++ b/types/wordpress__compose/higher-order/pure/index.d.ts
@@ -0,0 +1,8 @@
+import { ComponentType } from "@wordpress/element";
+
+// prettier-ignore
+declare function pure>(component: T):
+ T extends ComponentType ? ComponentType :
+ never;
+
+export default pure;
diff --git a/types/wordpress__compose/higher-order/with-global-events/index.d.ts b/types/wordpress__compose/higher-order/with-global-events/index.d.ts
new file mode 100644
index 0000000000..f0f55c2475
--- /dev/null
+++ b/types/wordpress__compose/higher-order/with-global-events/index.d.ts
@@ -0,0 +1,9 @@
+import { ComponentClass, ComponentType } from '@wordpress/element';
+
+// prettier-ignore
+declare function withGlobalEvents(eventMapper: { [k in keyof WindowEventMap]?: string }):
+ >(component: T) =>
+ T extends ComponentClass ? ComponentType :
+ never;
+
+export default withGlobalEvents;
diff --git a/types/wordpress__compose/higher-order/with-instance-id/index.d.ts b/types/wordpress__compose/higher-order/with-instance-id/index.d.ts
new file mode 100644
index 0000000000..3ffa40e232
--- /dev/null
+++ b/types/wordpress__compose/higher-order/with-instance-id/index.d.ts
@@ -0,0 +1,8 @@
+import { ComponentType } from '@wordpress/element';
+
+// prettier-ignore
+declare function withInstanceId>(wrapped: T):
+ T extends ComponentType ? ComponentType> :
+ never;
+
+export default withInstanceId;
diff --git a/types/wordpress__compose/higher-order/with-safe-timeout/index.d.ts b/types/wordpress__compose/higher-order/with-safe-timeout/index.d.ts
new file mode 100644
index 0000000000..d7aeadcc91
--- /dev/null
+++ b/types/wordpress__compose/higher-order/with-safe-timeout/index.d.ts
@@ -0,0 +1,8 @@
+import { ComponentType } from '@wordpress/element';
+
+// prettier-ignore
+declare function withSafeTimeout>(component: T):
+ T extends ComponentType ? ComponentType> :
+ never;
+
+export default withSafeTimeout;
diff --git a/types/wordpress__compose/higher-order/with-state/index.d.ts b/types/wordpress__compose/higher-order/with-state/index.d.ts
new file mode 100644
index 0000000000..87aedae4c3
--- /dev/null
+++ b/types/wordpress__compose/higher-order/with-state/index.d.ts
@@ -0,0 +1,9 @@
+import { ComponentClass, ComponentType } from '@wordpress/element';
+
+// prettier-ignore
+declare function withState(initialState: { [k in keyof SP]: SP[k] }):
+ >(component: T) =>
+ T extends ComponentType ? ComponentClass, SP> :
+ never;
+
+export default withState;
diff --git a/types/wordpress__compose/hooks/use-media-query/index.d.ts b/types/wordpress__compose/hooks/use-media-query/index.d.ts
new file mode 100644
index 0000000000..d86ae1a154
--- /dev/null
+++ b/types/wordpress__compose/hooks/use-media-query/index.d.ts
@@ -0,0 +1,9 @@
+/**
+ * Runs a media query and returns its value when it changes.
+ *
+ * @param query - Media Query.
+ * @returns return value of the media query.
+ */
+declare function useMediaQuery(query: string): boolean;
+
+export default useMediaQuery;
diff --git a/types/wordpress__compose/hooks/use-reduced-motion/index.d.ts b/types/wordpress__compose/hooks/use-reduced-motion/index.d.ts
new file mode 100644
index 0000000000..b25240d9bd
--- /dev/null
+++ b/types/wordpress__compose/hooks/use-reduced-motion/index.d.ts
@@ -0,0 +1,8 @@
+/**
+ * Hook returning whether the user has a preference for reduced motion.
+ *
+ * @returns Reduced motion preference value.
+ */
+declare function useReducedMotion(): boolean;
+
+export default useReducedMotion;
diff --git a/types/wordpress__compose/index.d.ts b/types/wordpress__compose/index.d.ts
new file mode 100644
index 0000000000..955b37c572
--- /dev/null
+++ b/types/wordpress__compose/index.d.ts
@@ -0,0 +1,35 @@
+// Type definitions for @wordpress/compose 3.4
+// Project: https://github.com/WordPress/gutenberg/tree/master/packages/compose/README.md
+// Definitions by: Derek Sifford
+// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
+// TypeScript Version: 3.5
+
+/**
+ * External dependencies
+ */
+import { flowRight } from 'lodash';
+
+// Utils
+export { default as createHigherOrderComponent } from './utils/create-higher-order-component';
+
+/**
+ * Composes multiple higher-order components into a single higher-order component. Performs right-to-left function
+ * composition, where each successive invocation is supplied the return value of the previous.
+ *
+ * @param {...Function} hocs The HOC functions to invoke.
+ *
+ * @return {Function} Returns the new composite function.
+ */
+export { flowRight as compose };
+
+// Higher-order components
+export { default as ifCondition } from './higher-order/if-condition';
+export { default as pure } from './higher-order/pure';
+export { default as withGlobalEvents } from './higher-order/with-global-events';
+export { default as withInstanceId } from './higher-order/with-instance-id';
+export { default as withSafeTimeout } from './higher-order/with-safe-timeout';
+export { default as withState } from './higher-order/with-state';
+
+// Hooks
+export { default as useMediaQuery } from './hooks/use-media-query';
+export { default as useReducedMotion } from './hooks/use-reduced-motion';
diff --git a/types/wordpress__compose/tsconfig.json b/types/wordpress__compose/tsconfig.json
new file mode 100644
index 0000000000..227ea5f0d3
--- /dev/null
+++ b/types/wordpress__compose/tsconfig.json
@@ -0,0 +1,33 @@
+{
+ "compilerOptions": {
+ "module": "commonjs",
+ "lib": ["dom", "es6"],
+ "jsx": "preserve",
+ "noImplicitAny": true,
+ "noImplicitThis": true,
+ "strictNullChecks": true,
+ "strictFunctionTypes": true,
+ "baseUrl": "../",
+ "typeRoots": ["../"],
+ "types": [],
+ "noEmit": true,
+ "forceConsistentCasingInFileNames": true,
+ "paths": {
+ "@wordpress/compose": ["wordpress__compose"],
+ "@wordpress/element": ["wordpress__element"]
+ }
+ },
+ "files": [
+ "index.d.ts",
+ "higher-order/if-condition/index.d.ts",
+ "higher-order/pure/index.d.ts",
+ "higher-order/with-global-events/index.d.ts",
+ "higher-order/with-instance-id/index.d.ts",
+ "higher-order/with-safe-timeout/index.d.ts",
+ "higher-order/with-state/index.d.ts",
+ "hooks/use-media-query/index.d.ts",
+ "hooks/use-reduced-motion/index.d.ts",
+ "utils/create-higher-order-component/index.d.ts",
+ "wordpress__compose-tests.tsx"
+ ]
+}
diff --git a/types/wordpress__compose/tslint.json b/types/wordpress__compose/tslint.json
new file mode 100644
index 0000000000..3db14f85ea
--- /dev/null
+++ b/types/wordpress__compose/tslint.json
@@ -0,0 +1 @@
+{ "extends": "dtslint/dt.json" }
diff --git a/types/wordpress__compose/utils/create-higher-order-component/index.d.ts b/types/wordpress__compose/utils/create-higher-order-component/index.d.ts
new file mode 100644
index 0000000000..3adea539d8
--- /dev/null
+++ b/types/wordpress__compose/utils/create-higher-order-component/index.d.ts
@@ -0,0 +1,12 @@
+import { ComponentType } from '@wordpress/element';
+
+// tslint:disable:no-unnecessary-generics
+// prettier-ignore
+declare function createHigherOrderComponent(
+ mapComponentToEnhancedComponent: (component: ComponentType) => ComponentType,
+ modifierName: string
+): >(component: T) =>
+ T extends ComponentType ? ComponentType> :
+ never;
+
+export default createHigherOrderComponent;
diff --git a/types/wordpress__compose/wordpress__compose-tests.tsx b/types/wordpress__compose/wordpress__compose-tests.tsx
new file mode 100644
index 0000000000..9103269397
--- /dev/null
+++ b/types/wordpress__compose/wordpress__compose-tests.tsx
@@ -0,0 +1,139 @@
+import { Component } from '@wordpress/element';
+import * as C from '@wordpress/compose';
+
+//
+// utils/create-higher-order-component
+//
+(() => {
+ const withFoo = C.createHigherOrderComponent<{ foo: string }>(
+ OriginalComponent => props => ,
+ 'withFoo'
+ );
+
+ const Enhanced = withFoo(({ foo, bar }: { foo: string; bar: string }) => (
+
+ {foo} and {bar}
+
+ ));
+
+ ;
+})();
+
+//
+// higher-order/if-condition
+//
+(() => {
+ interface Props {
+ isVisible: boolean;
+ foo: string;
+ bar: string;
+ }
+ const Original = ({ isVisible, foo, bar }: Props) => (
+
+ {foo} and {bar}
+
+ );
+ const Enhanced = C.ifCondition(({ isVisible }) => isVisible)(Original);
+ ;
+})();
+
+//
+// higher-order/pure
+//
+(() => {
+ const Original = ({ foo, bar }: { foo: string; bar: string }) => (
+
+ {foo} and {bar}
+
+ );
+
+ const Enhanced = C.pure(Original);
+
+ ;
+ ;
+})();
+
+//
+// higher-order/with-global-events
+//
+(() => {
+ const Enhanced = C.withGlobalEvents({ resize: 'handleResize' })(
+ class extends Component<{ foo: string }> {
+ handleResize() {
+ console.log('resized');
+ }
+ render() {
+ return {this.props.foo}
;
+ }
+ }
+ );
+ ;
+})();
+
+//
+// higher-order/with-instance-id
+//
+(() => {
+ interface Props {
+ foo: string;
+ instanceId: string;
+ }
+ const Enhanced = C.withInstanceId(({ foo, instanceId }: Props) => {foo}
);
+ ;
+})();
+
+//
+// higher-order/with-safe-timeout
+//
+(() => {
+ interface Props {
+ foo: string;
+ setTimeout: typeof setTimeout;
+ }
+ const Enhanced = C.withSafeTimeout(({ foo, setTimeout }: Props) => (
+ setTimeout(() => console.log('Hello World', 100))}>{foo}
+ ));
+ ;
+})();
+
+//
+// higher-order/with-state
+//
+(() => {
+ interface Props {
+ count: number;
+ setState(obj: any): void;
+ }
+ const Enhanced = C.withState<{ count: number }>({ count: 0 })(({ count, setState }: Props) => (
+
+ ));
+ ;
+})();
+
+//
+// hooks/use-media-query
+//
+(() => {
+ const MyComponent = () => {
+ const shouldRender = C.useMediaQuery('(min-width: 800px)');
+ if (shouldRender) {
+ return Hello World
;
+ }
+ return null;
+ };
+ ;
+})();
+
+//
+// hooks/use-reduced-motion
+//
+(() => {
+ const MyComponent = () => {
+ const shouldUseReducedMotiion = C.useReducedMotion();
+ if (shouldUseReducedMotiion) {
+ return Using reduced motion!
;
+ }
+ return Not using reduced motion!
;
+ };
+ ;
+})();