diff --git a/types/next/document.d.ts b/types/next/document.d.ts index 38e20e00c0..0955877d61 100644 --- a/types/next/document.d.ts +++ b/types/next/document.d.ts @@ -1,10 +1,43 @@ import * as React from "react"; + import { NextContext } from "."; +export interface RenderPageResponse { + buildManifest: { [key: string]: any }; + chunks: { + names: string[]; + filenames: string[]; + }; + html?: string; + head: Array>; + errorHtml: string; +} + +export interface PageProps { + url: string; +} + +export interface AnyPageProps extends PageProps { + [key: string]: any; +} + +export type Enhancer = (page: React.ComponentType

) => React.ComponentType; + +/** + * Context object used inside `Document` + */ +export interface NextDocumentContext extends NextContext { + /** A callback that executes the actual React rendering logic (synchronously) */ + renderPage(enhancer?: Enhancer): RenderPageResponse; // tslint:disable-line:no-unnecessary-generics +} + export interface DocumentProps { __NEXT_DATA__?: any; dev?: boolean; - chunks?: string[]; + chunks?: { + names: string[]; + filenames: string[]; + }; html?: string; head?: Array>; errorHtml?: string; @@ -13,21 +46,9 @@ export interface DocumentProps { [key: string]: any; } -/** - * Context object used inside `Document` - */ -export interface NextDocumentContext extends NextContext { - /** A callback that executes the actual React rendering logic (synchronously) */ - renderPage( - cb?: (enhancer: () => JSX.Element) => React.ComponentType - ): { - [key: string]: any - }; -} - export class Head extends React.Component {} export class Main extends React.Component {} export class NextScript extends React.Component {} export default class extends React.Component { - static getInitialProps(ctx: NextContext): DocumentProps; + static getInitialProps(ctx: NextDocumentContext): Promise | DocumentProps; } diff --git a/types/next/test/next-document-tests.tsx b/types/next/test/next-document-tests.tsx index 2b3257cd25..f727262b0e 100644 --- a/types/next/test/next-document-tests.tsx +++ b/types/next/test/next-document-tests.tsx @@ -1,7 +1,7 @@ -import Document, { Head, Main, NextScript, NextDocumentContext } from 'next/document'; +import Document, { DocumentProps, Enhancer, Head, Main, NextScript, NextDocumentContext, PageProps } from 'next/document'; import * as React from "react"; -const results = ( +const basicResults = ( @@ -11,16 +11,18 @@ const results = ( ); -const Wrapper: React.SFC = ({ children }) => {children}; - -export default class MyDocument extends Document { +class MyDoc extends Document { static async getInitialProps({ renderPage }: NextDocumentContext) { - // Without callback - const page = renderPage(); - // With callback - const differentPage = renderPage(App => props => ); + // without callback + const _page = renderPage(); + + // with callback + const enhancer: Enhancer = (App) => (props) => (); + const { html, head, errorHtml, chunks, buildManifest } = renderPage(enhancer); + const style = {}; - return { ...page, style }; + + return { html, head, errorHtml, chunks, buildManifest, style }; } render() { @@ -33,8 +35,45 @@ export default class MyDocument extends Document {

+ {this.props.children} ); } } + +const extendedResults = ( + + + + +

Hey there

+
+); + +const renderPage: NextDocumentContext['renderPage'] = (enhancer) => ({ + buildManifest: {}, + chunks: { names: [], filenames: [] }, + html: '', + head: [], + errorHtml: '', +}); + +interface PageInitialProps extends PageProps { + foo: string; + bar: number; +} + +interface ProcessedInitialProps { + fooLength: number; + bar: boolean; +} + +const enhancerExplicit: Enhancer = (App) => (props) => (); +const enhancerInferred = (App: React.ComponentType) => ({ foo, bar }: PageInitialProps) => (); +const explicitEnhancerRenderResponse = renderPage(enhancerExplicit); +const inferredEnhancerRenderResponse = renderPage(enhancerInferred); +const defaultedTypesRenderResponse = renderPage((App) => (props) => ()); +const defaultedTypesExtendedRenderResponse = renderPage((App) => (props) => ()); +const explicitTypesRenderResponseOne = renderPage((App) => (props) => ()); +const explicitTypesRenderResponseTwo = renderPage((App) => ({ foo, bar }) => ());