diff --git a/types/react-loadable/index.d.ts b/types/react-loadable/index.d.ts index 6220b23ea6..8b591d3f3a 100644 --- a/types/react-loadable/index.d.ts +++ b/types/react-loadable/index.d.ts @@ -1,184 +1,190 @@ // Type definitions for react-loadable 5.3 // Project: https://github.com/thejameskyle/react-loadable#readme -// Definitions by: Diogo Franco , Oden S. +// Definitions by: Diogo Franco , Oden S. , Ian Ker-Seymer // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped // TypeScript Version: 2.4 -import * as React from 'react'; +/// -export interface LoadingComponentProps { - isLoading: boolean; - pastDelay: boolean; - timedOut: boolean; - error: any; +declare namespace Loadable { + interface LoadingComponentProps { + isLoading: boolean; + pastDelay: boolean; + timedOut: boolean; + error: any; + } + + type Options = OptionsWithoutRender | OptionsWithRender; + + interface CommonOptions { + /** + * React component displayed after delay until loader() succeeds. Also responsible for displaying errors. + * + * If you don't want to render anything you can pass a function that returns null + * (this is considered a valid React component). + */ + // NOTE: () => null is only needed until React.SFC supports components returning null + loading: React.ComponentType | (() => null); + /** + * Defaults to 200, in milliseconds. + * + * Only show the loading component if the loader() has taken this long to succeed or error. + */ + delay?: number | false | null; + /** + * Disabled by default. + * + * After the specified time in milliseconds passes, the component's `timedOut` prop will be set to true. + */ + timeout?: number | false | null; + + /** + * Optional array of module paths that `Loadable.Capture`'s `report` function will be applied on during + * server-side rendering. This helps the server know which modules were imported/used during SSR. + * ```ts + * Loadable({ + * loader: () => import('./my-component'), + * modules: ['./my-component'], + * }); + * ``` + */ + modules?: string[]; + + /** + * An optional function which returns an array of Webpack module ids which you can get + * with require.resolveWeak. This is used by the client (inside `Loadable.preloadReady`) to + * guarantee each webpack module is preloaded before the first client render. + * ```ts + * Loadable({ + * loader: () => import('./Foo'), + * webpack: () => [require.resolveWeak('./Foo')], + * }); + * ``` + */ + webpack?: () => number[]; + } + + interface OptionsWithoutRender extends CommonOptions { + /** + * Function returning a promise which returns a React component displayed on success. + * + * Resulting React component receives all the props passed to the generated component. + */ + loader(): Promise | { default: React.ComponentType }>; + } + + interface OptionsWithRender extends CommonOptions { + /** + * Function returning a promise which returns an object to be passed to `render` on success. + */ + loader(): Promise; + /** + * If you want to customize what gets rendered from your loader you can also pass `render`. + * + * Note: If you want to load multiple resources at once, you can also use `Loadable.Map`. + * + * ```ts + * Loadable({ + * // ... + * render(loaded, props) { + * const Component = loaded.default; + * return + * } + * }); + * ``` + */ + render(loaded: Exports, props: Props): React.ReactNode; + + // NOTE: render is not optional if the loader return type is not compatible with the type + // expected in `OptionsWithoutRender`. If you do not want to provide a render function, ensure that your + // function is returning a promise for a React.ComponentType or is the result of import()ing a module + // that has a component as its `default` export. + } + + interface OptionsWithMap extends CommonOptions { + /** + * An object containing functions which return promises, which resolve to an object to be passed to `render` on success. + */ + loader: { + [P in keyof Exports]: () => Promise + }; + /** + * If you want to customize what gets rendered from your loader you can also pass `render`. + * + * Note: If you want to load multiple resources at once, you can also use `Loadable.Map`. + * + * ```ts + * Loadable({ + * // ... + * render(loaded, props) { + * const Component = loaded.default; + * return + * } + * }); + * ``` + */ + render(loaded: Exports, props: Props): React.ReactNode; + } + + interface LoadableComponent { + /** + * The generated component has a static method preload() for calling the loader function ahead of time. + * This is useful for scenarios where you think the user might do something next and want to load the + * next component eagerly. + * + * Note: preload() intentionally does not return a promise. You should not be depending on the timing of + * preload(). It's meant as a performance optimization, not for creating UI logic. + */ + preload(): void; + } + + interface LoadableCaptureProps { + /** + * Function called for every moduleName that is rendered via React Loadable. + */ + report: (moduleName: string) => void; + } + + interface Loadable { + (options: Options): React.ComponentType & LoadableComponent; + Map(options: OptionsWithMap): React.ComponentType & LoadableComponent; + + /** + * This will call all of the LoadableComponent.preload methods recursively until they are all + * resolved. Allowing you to preload all of your dynamic modules in environments like the server. + * ```ts + * Loadable.preloadAll().then(() => { + * app.listen(3000, () => { + * console.log('Running on http://localhost:3000/'); + * }); + * }); + * ``` + */ + preloadAll(): Promise; + + /** + * Check for modules that are already loaded in the browser and call the matching + * `LoadableComponent.preload` methods. + * ```ts + * window.main = () => { + * Loadable.preloadReady().then(() => { + * ReactDOM.hydrate( + * , + * document.getElementById('app'), + * ); + * }); + * }; + * ``` + */ + preloadReady(): Promise; + + Capture: React.ComponentType; + } } -export type Options = OptionsWithoutRender | OptionsWithRender; +declare const LoadableExport: Loadable.Loadable; -export interface CommonOptions { - /** - * React component displayed after delay until loader() succeeds. Also responsible for displaying errors. - * - * If you don't want to render anything you can pass a function that returns null - * (this is considered a valid React component). - */ - // NOTE: () => null is only needed until React.SFC supports components returning null - loading: React.ComponentType | (() => null); - /** - * Defaults to 200, in milliseconds. - * - * Only show the loading component if the loader() has taken this long to succeed or error. - */ - delay?: number | false | null; - /** - * Disabled by default. - * - * After the specified time in milliseconds passes, the component's `timedOut` prop will be set to true. - */ - timeout?: number | false | null; - - /** - * Optional array of module paths that `Loadable.Capture`'s `report` function will be applied on during - * server-side rendering. This helps the server know which modules were imported/used during SSR. - * ```ts - * Loadable({ - * loader: () => import('./my-component'), - * modules: ['./my-component'], - * }); - * ``` - */ - modules?: string[]; - - /** - * An optional function which returns an array of Webpack module ids which you can get - * with require.resolveWeak. This is used by the client (inside `Loadable.preloadReady`) to - * guarantee each webpack module is preloaded before the first client render. - * ```ts - * Loadable({ - * loader: () => import('./Foo'), - * webpack: () => [require.resolveWeak('./Foo')], - * }); - * ``` - */ - webpack?: () => number[]; +/* tslint:disable-next-line */ +declare module "react-loadable" { + export = LoadableExport; } - -export interface OptionsWithoutRender extends CommonOptions { - /** - * Function returning a promise which returns a React component displayed on success. - * - * Resulting React component receives all the props passed to the generated component. - */ - loader(): Promise | { default: React.ComponentType }>; -} - -export interface OptionsWithRender extends CommonOptions { - /** - * Function returning a promise which returns an object to be passed to `render` on success. - */ - loader(): Promise; - /** - * If you want to customize what gets rendered from your loader you can also pass `render`. - * - * Note: If you want to load multiple resources at once, you can also use `Loadable.Map`. - * - * ```ts - * Loadable({ - * // ... - * render(loaded, props) { - * const Component = loaded.default; - * return - * } - * }); - * ``` - */ - render(loaded: Exports, props: Props): React.ReactNode; - - // NOTE: render is not optional if the loader return type is not compatible with the type - // expected in `OptionsWithoutRender`. If you do not want to provide a render function, ensure that your - // function is returning a promise for a React.ComponentType or is the result of import()ing a module - // that has a component as its `default` export. -} - -export interface OptionsWithMap extends CommonOptions { - /** - * An object containing functions which return promises, which resolve to an object to be passed to `render` on success. - */ - loader: { - [P in keyof Exports]: () => Promise - }; - /** - * If you want to customize what gets rendered from your loader you can also pass `render`. - * - * Note: If you want to load multiple resources at once, you can also use `Loadable.Map`. - * - * ```ts - * Loadable({ - * // ... - * render(loaded, props) { - * const Component = loaded.default; - * return - * } - * }); - * ``` - */ - render(loaded: Exports, props: Props): React.ReactNode; -} - -export interface LoadableComponent { - /** - * The generated component has a static method preload() for calling the loader function ahead of time. - * This is useful for scenarios where you think the user might do something next and want to load the - * next component eagerly. - * - * Note: preload() intentionally does not return a promise. You should not be depending on the timing of - * preload(). It's meant as a performance optimization, not for creating UI logic. - */ - preload(): void; -} - -export interface LoadableCaptureProps { - /** - * Function called for every moduleName that is rendered via React Loadable. - */ - report: (moduleName: string) => void; -} - -export interface Loadable { - (options: Options): React.ComponentType & LoadableComponent; - Map(options: OptionsWithMap): React.ComponentType & LoadableComponent; - - /** - * This will call all of the LoadableComponent.preload methods recursively until they are all - * resolved. Allowing you to preload all of your dynamic modules in environments like the server. - * ```ts - * Loadable.preloadAll().then(() => { - * app.listen(3000, () => { - * console.log('Running on http://localhost:3000/'); - * }); - * }); - * ``` - */ - preloadAll(): Promise; - - /** - * Check for modules that are already loaded in the browser and call the matching - * `LoadableComponent.preload` methods. - * ```ts - * window.main = () => { - * Loadable.preloadReady().then(() => { - * ReactDOM.hydrate( - * , - * document.getElementById('app'), - * ); - * }); - * }; - * ``` - */ - preloadReady(): Promise; - - Capture: React.ComponentType; -} - -declare const LoadableExport: Loadable; -export default LoadableExport; diff --git a/types/react-loadable/test/index.tsx b/types/react-loadable/test/index.tsx index ee5ec82119..5045fdf125 100644 --- a/types/react-loadable/test/index.tsx +++ b/types/react-loadable/test/index.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; -import Loadable, { LoadingComponentProps } from 'react-loadable'; +import Loadable = require('react-loadable'); -class LoadingComponent extends React.Component { +class LoadingComponent extends React.Component { render() { return (