diff --git a/types/create-subscription/create-subscription-tests.tsx b/types/create-subscription/create-subscription-tests.tsx
new file mode 100644
index 0000000000..891adc5ede
--- /dev/null
+++ b/types/create-subscription/create-subscription-tests.tsx
@@ -0,0 +1,119 @@
+import * as React from "react";
+import { createSubscription, Subscription } from "create-subscription";
+
+//
+// Example: Subscribing to event dispatchers
+// https://github.com/facebook/react/blob/fa7fa812c70084e139d13437fb204fcdf9152299/packages/create-subscription/README.md#subscribing-to-event-dispatchers
+// ----------------------------------------------------------------------------
+
+// Start with a simple component.
+// In this case, it's a functional component, but it could have been a class.
+function FollowerComponent({ followersCount }: { followersCount: number }) {
+ return
You have {followersCount} followers!
;
+}
+
+interface EventDispatcher {
+ value: T;
+ addEventListener(eventName: "change", onChange: (newValue: T) => any): void;
+ removeEventListener(eventName: "change", onChange: (newValue: T) => any): void;
+}
+
+// Create a wrapper component to manage the subscription.
+// $ExpectType Subscription, number>
+const EventHandlerSubscription = createSubscription({
+ getCurrentValue: (eventDispatcher: EventDispatcher) => eventDispatcher.value,
+ subscribe: (eventDispatcher: EventDispatcher, callback) => {
+ const onChange = (event: any) => callback(eventDispatcher.value);
+ eventDispatcher.addEventListener("change", onChange);
+ return () => eventDispatcher.removeEventListener("change", onChange);
+ }
+});
+
+declare const eventDispatcher: EventDispatcher;
+
+// Your component can now be used as shown below.
+// In this example, 'eventDispatcher' represents a generic event dispatcher.
+
+ {value => {
+ // $ExpectType number
+ const followersCount = value;
+ return ;
+ }}
+;
+
+//
+// Example: Subscribing to event dispatchers
+// https://github.com/facebook/react/blob/fa7fa812c70084e139d13437fb204fcdf9152299/packages/create-subscription/README.md#subscribing-to-a-promise
+// ----------------------------------------------------------------------------
+
+// Start with a simple component.
+const LoadingComponent: React.SFC<{ loadingStatus: string | undefined }> = ({ loadingStatus }) => {
+ if (loadingStatus === undefined) {
+ // Loading
+ } else if (loadingStatus === null) {
+ // Error
+ } else {
+ // Success
+ }
+ return null;
+};
+
+// Wrap the functional component with a subscriber HOC.
+// This HOC will manage subscriptions and pass values to the decorated component.
+// It will add and remove subscriptions in an async-safe way when props change.
+// $ExpectType Subscription, string | undefined>
+const PromiseSubscription = createSubscription({
+ getCurrentValue: promise => {
+ // There is no way to synchronously read a Promise's value,
+ // So this method should return undefined.
+ return undefined;
+ },
+ subscribe: (promise: Promise, callback: (newValue: string | undefined) => void) => {
+ promise.then(
+ // Success
+ callback,
+ // Failure
+ () => callback(undefined)
+ );
+
+ // There is no way to "unsubscribe" from a Promise.
+ // create-subscription will still prevent stale values from rendering.
+ return () => {};
+ }
+});
+
+declare const loadingPromise: Promise;
+
+// Your component can now be used as shown below.
+
+ {value => {
+ // $ExpectType string | undefined
+ const loadingStatus = value;
+ return ;
+ }}
+;
+
+//
+// Error cases
+// ----------------------------------------------------------------------------
+
+declare const wrongPromise: Promise;
+
+// $ExpectError
+
+ {value => null}
+;
+
+// $ExpectError
+const MismatchSubscription = createSubscription({
+ getCurrentValue: (a: number) => null,
+ subscribe: (a: string, callback) => (() => undefined)
+});
+
+// $ExpectError
+const NoUnsubscribe = createSubscription({
+ getCurrentValue: (a: number) => a,
+ subscribe: (a: number, callback) => {
+ // oops, should've returned a callback here
+ }
+});
diff --git a/types/create-subscription/index.d.ts b/types/create-subscription/index.d.ts
new file mode 100644
index 0000000000..28cfbd4e31
--- /dev/null
+++ b/types/create-subscription/index.d.ts
@@ -0,0 +1,44 @@
+// Type definitions for create-subscription 16.4
+// Project: https://github.com/facebook/react/tree/master/packages/create-subscription
+// Definitions by: Asana
+// Vincent Siao
+// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
+// TypeScript Version: 2.3
+
+import * as React from "react";
+
+export interface SubscriptionProps {
+ children: (value: T) => React.ReactNode;
+ source: S;
+}
+
+export interface SubscriptionState {
+ source: S;
+ value: T;
+}
+
+export interface Subscription extends React.ComponentClass> {}
+export type Unsubscribe = () => any;
+
+export interface SubscriptionConfig {
+ /**
+ * Synchronously gets the value for the subscribed property.
+ * Return undefined if the subscribable value is undefined,
+ * Or does not support synchronous reading (e.g. native Promise).
+ */
+ getCurrentValue: (source: S) => T;
+
+ /**
+ * Set up a subscription for the subscribable value in props, and return an unsubscribe function.
+ * Return false to indicate the property cannot be unsubscribed from (e.g. native Promises).
+ * Due to the variety of change event types, subscribers should provide their own handlers.
+ * Those handlers should not attempt to update state though;
+ * They should call the callback() instead when a subscription changes.
+ */
+ subscribe: (
+ source: S,
+ callback: (newValue: T) => void
+ ) => Unsubscribe;
+}
+
+export function createSubscription(config: SubscriptionConfig): Subscription;
diff --git a/types/create-subscription/tsconfig.json b/types/create-subscription/tsconfig.json
new file mode 100644
index 0000000000..0e42cd3adb
--- /dev/null
+++ b/types/create-subscription/tsconfig.json
@@ -0,0 +1,24 @@
+{
+ "compilerOptions": {
+ "jsx": "react",
+ "module": "commonjs",
+ "lib": [
+ "es6"
+ ],
+ "noImplicitAny": true,
+ "noImplicitThis": true,
+ "strictFunctionTypes": true,
+ "strictNullChecks": true,
+ "baseUrl": "../",
+ "typeRoots": [
+ "../"
+ ],
+ "types": [],
+ "noEmit": true,
+ "forceConsistentCasingInFileNames": true
+ },
+ "files": [
+ "index.d.ts",
+ "create-subscription-tests.tsx"
+ ]
+}
diff --git a/types/create-subscription/tslint.json b/types/create-subscription/tslint.json
new file mode 100644
index 0000000000..3db14f85ea
--- /dev/null
+++ b/types/create-subscription/tslint.json
@@ -0,0 +1 @@
+{ "extends": "dtslint/dt.json" }