From 205aa683dcf659c51e0111e556cd188e46788f6a Mon Sep 17 00:00:00 2001 From: Drew Hays Date: Wed, 5 Jul 2017 10:31:06 -0700 Subject: [PATCH 1/6] Add types for next.js --- types/next/index.d.ts | 162 +++++++++++++++++++++++ types/next/next-tests.ts | 54 ++++++++ types/next/tests/next-document-tests.tsx | 12 ++ types/next/tests/next-dynamic-tests.tsx | 23 ++++ types/next/tests/next-error-tests.tsx | 6 + types/next/tests/next-head-tests.tsx | 9 ++ types/next/tests/next-link-tests.tsx | 13 ++ types/next/tests/next-router-tests.tsx | 50 +++++++ types/next/tsconfig.json | 31 +++++ types/next/tslint.json | 18 +++ 10 files changed, 378 insertions(+) create mode 100644 types/next/index.d.ts create mode 100644 types/next/next-tests.ts create mode 100644 types/next/tests/next-document-tests.tsx create mode 100644 types/next/tests/next-dynamic-tests.tsx create mode 100644 types/next/tests/next-error-tests.tsx create mode 100644 types/next/tests/next-head-tests.tsx create mode 100644 types/next/tests/next-link-tests.tsx create mode 100644 types/next/tests/next-router-tests.tsx create mode 100644 types/next/tsconfig.json create mode 100644 types/next/tslint.json diff --git a/types/next/index.d.ts b/types/next/index.d.ts new file mode 100644 index 0000000000..ab57dd6241 --- /dev/null +++ b/types/next/index.d.ts @@ -0,0 +1,162 @@ +// Type definitions for next +// Project: https://github.com/zeit/next.js +// Definitions by: Drew Hays +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +/// + +declare module 'next' { + import * as http from 'http'; + import * as url from 'url'; + + type UrlLike = url.UrlObject | url.Url; + + interface ServerConfig { + // known keys + webpack?: any; + webpackDevMiddleware?: any; + poweredByHeader?: boolean; + distDir?: string; + assetPrefix?: string; + configOrigin?: string; + useFileSystemPublicRoutes?: boolean; + + // and since this is a config, it can take anything else, too. + [key: string]: any; + } + + interface ServerOptions { + dir?: string; + dev?: boolean; + staticMarkup?: boolean; + quiet?: boolean; + conf?: ServerConfig; + } + + interface Server { + handleRequest(req: http.IncomingMessage, res: http.ServerResponse, parsedUrl?: UrlLike): Promise; + getRequestHandler(): (req: http.IncomingMessage, res: http.ServerResponse, parsedUrl?: UrlLike) => Promise; + prepare(): Promise; + close(): Promise; + defineRoutes(): Promise; + start(): Promise; + run(req: http.IncomingMessage, res: http.ServerResponse, parsedUrl: UrlLike): Promise; + + render(req: http.IncomingMessage, res: http.ServerResponse, pathname: string, query: {[key: string]: any}, parsedUrl: UrlLike): Promise; + renderError(err: any, req: http.IncomingMessage, res: http.ServerResponse, pathname: string, query: {[key: string]: any}): Promise; + render404(req: http.IncomingMessage, res: http.ServerResponse, parsedUrl: UrlLike): Promise; + renderToHTML(req: http.IncomingMessage, res: http.ServerResponse, pathname: string, query: {[key: string]: any}): Promise; + renderErrorToHTML(err: any, req: http.IncomingMessage, res: http.ServerResponse, pathname: string, query: {[key: string]: any}): Promise; + + serveStatic(req: http.IncomingMessage, res: http.ServerResponse, path: string): Promise; + isServeableUrl(path: string): boolean; + isInternalUrl(req: http.IncomingMessage): boolean; + readBuildId(): string; + handleBuildId(buildId: string, res: http.ServerResponse): boolean; + getCompilationError(page: string, req: http.IncomingMessage, res: http.ServerResponse): Promise; + handleBuildHash(filename: string, hash: string, res: http.ServerResponse): void; + send404(res: http.ServerResponse): void; + } + + export default function(options?: ServerOptions): Server; +} + +declare module 'next/error' { + import * as React from 'react'; + export default class extends React.Component<{statusCode: number}, {}> {} +} + +declare module 'next/head' { + import * as React from 'react'; + function defaultHead(): JSX.Element[]; + export default class extends React.Component<{}, {}> {} +} + +declare module 'next/document' { + interface DocumentProps { + __NEXT_DATA__?: any; + dev?: boolean; + chunks?: string[]; + head?: Array>; + styles?: Array>; + [key: string]: any; + } + + class Head extends React.Component {} + class Main extends React.Component<{}, {}> {} + class NextScript extends React.Component<{}, {}> {} + export default class extends React.Component {} +} + +declare module 'next/link' { + import * as url from 'url'; + type UrlLike = url.UrlObject | url.Url; + interface LinkState { + prefetch?: boolean; + shallow?: boolean; + scroll?: boolean; + replace?: boolean; + onError?(error: any): void; + href?: string | UrlLike; + as?: string | UrlLike; + children: React.ReactElement; + } + + export default class extends React.Component {} +} + +declare module 'next/dynamic' { + interface DynamicOptions { + loading?: React.ComponentType; + ssr?: boolean; + modules?(props: TCProps & TLProps): { [key: string]: Promise> }; + render?(props: TCProps & TLProps, modules: { [key: string]: React.ComponentType }): void; + } + + class SameLoopPromise extends Promise { + constructor(executor: (resolve: (value?: T) => void, reject: (reason?: any) => void) => void); + setResult(value: T): void; + setError(value: any): void; + runIfNeeded(): void; + } + export default function(componentPromise: Promise>, options?: DynamicOptions): React.ComponentType; +} + +declare module 'next/router' { + import * as url from 'url'; + + interface EventChangeOptions { + shallow?: boolean; + [key: string]: any; + } + + type RouterCallback = () => void; + interface SingletonRouter { + readyCallbacks: RouterCallback[]; + ready(cb: RouterCallback): void; + + // router properties + readonly components: { [key: string]: { Component: React.ComponentType, err: any } }; + readonly pathname: string; + readonly route: string; + readonly asPath: string; + readonly query: { [key: string]: any }; + + // router methods + reload(route: string): Promise; + back(): void; + push(url: string, as?: string, options?: EventChangeOptions): Promise; + replace(url: string, as?: string, options?: EventChangeOptions): Promise; + prefetch(url: string): Promise>; + + // router events + onAppUpdated?(nextRoute: string): void; + onRouteChangeStart?(url: string): void; + onBeforeHistoryChange?(as: string): void; + onRouteChangeComplete?(url: string): void; + onRouteChangeError?(error: any, url: string): void; + } + + const Singleton: SingletonRouter; + export default Singleton; +} diff --git a/types/next/next-tests.ts b/types/next/next-tests.ts new file mode 100644 index 0000000000..3c216d770d --- /dev/null +++ b/types/next/next-tests.ts @@ -0,0 +1,54 @@ +import createServer from 'next'; +import * as http from 'http'; +import * as url from 'url'; + +const defaultServer = createServer(); +const server = createServer({ + dir: '..', + quiet: true, + conf: { + distDir: './dist', + useFileSystemPublicRoutes: false, + anotherProperty: { + key: true + } + } +}); + +const voidFunc = () => {}; +const stringFunc = (x: string) => x.split('\n'); + +server.prepare().then(voidFunc); +server.close().then(voidFunc); +server.defineRoutes().then(voidFunc); +server.start().then(voidFunc); + +const parsedUrl = url.parse('https://www.example.com'); +const req: http.IncomingMessage = null; +const res: http.ServerResponse = null; +const handler = server.getRequestHandler(); + +handler(req, res); +handler(req, res, parsedUrl).then(voidFunc); +server.run(req, res, parsedUrl).then(voidFunc); + +server.render(req, res, '/path/to/resource', null, parsedUrl).then(voidFunc); +server.render(req, res, '/path/to/resource', { key: 'value' }, parsedUrl).then(voidFunc); +server.renderError(new Error(), req, res, '/path/to/resource', { key: 'value' }).then(voidFunc); +server.renderError('this can be an error, too!', req, res, '/path/to/resource', { key: 'value' }).then(voidFunc); +server.render404(req, res, parsedUrl).then(voidFunc); + +server.renderToHTML(req, res, '/path/to/resource', { foo: 'bar' }).then(x => x.split('\n')); +server.renderErrorToHTML(new Error(), req, res, '/path/to/resource', { foo: 'bar' }).then(x => x.split('\n')); + +server.serveStatic(req, res, '/path/to/thing').then(voidFunc); + +let b: boolean; +b = server.isServeableUrl('/path/to/thing'); +b = server.isInternalUrl(req); +b = server.handleBuildId('{buildId}', res); + +const s: string = server.readBuildId(); +server.getCompilationError('page', req, res).then(err => err.thisIsAnAny); +server.handleBuildHash('filename', 'hash', res); +server.send404(res); diff --git a/types/next/tests/next-document-tests.tsx b/types/next/tests/next-document-tests.tsx new file mode 100644 index 0000000000..4fbb25948b --- /dev/null +++ b/types/next/tests/next-document-tests.tsx @@ -0,0 +1,12 @@ +import Document, * as document from 'next/document'; +import * as React from 'react'; + +const results = ( + + + + + + + +); diff --git a/types/next/tests/next-dynamic-tests.tsx b/types/next/tests/next-dynamic-tests.tsx new file mode 100644 index 0000000000..be10954de9 --- /dev/null +++ b/types/next/tests/next-dynamic-tests.tsx @@ -0,0 +1,23 @@ +import dynamic, * as d from 'next/dynamic'; +import * as React from 'react'; + +// typically you'd use this with an esnext-style import() statement, but we'll make do without +interface DynamicComponentProps { + foo: string; + bar: number; +} +async function getComponent() { + return ( + (props: DynamicComponentProps) =>
I'm an async component! {props.foo} {props.bar}
+ ); +} + +interface LoadingComponentProps { + baz: boolean; +} + +const DynamicComponent = dynamic(getComponent(), { + loading: (props: LoadingComponentProps) =>
Loading! {props.baz}
+}); + +const jsx = (); diff --git a/types/next/tests/next-error-tests.tsx b/types/next/tests/next-error-tests.tsx new file mode 100644 index 0000000000..38692ac6de --- /dev/null +++ b/types/next/tests/next-error-tests.tsx @@ -0,0 +1,6 @@ +import * as React from 'react'; +import ErrorComponent from 'next/error'; + +const result = ( + +); diff --git a/types/next/tests/next-head-tests.tsx b/types/next/tests/next-head-tests.tsx new file mode 100644 index 0000000000..eaf6754b49 --- /dev/null +++ b/types/next/tests/next-head-tests.tsx @@ -0,0 +1,9 @@ +import Head, * as head from 'next/head'; +import * as React from 'react'; + +const elements: JSX.Element[] = head.defaultHead(); +const jsx = ( + + {elements} + +); diff --git a/types/next/tests/next-link-tests.tsx b/types/next/tests/next-link-tests.tsx new file mode 100644 index 0000000000..281c6aff7a --- /dev/null +++ b/types/next/tests/next-link-tests.tsx @@ -0,0 +1,13 @@ +import Link from 'next/link'; +import * as React from 'react'; + +const links = ( +
+ { console.log("Handled error!", e); }} prefetch replace scroll shallow> + Gotta link to somewhere! + + + All props are optional! + +
+); diff --git a/types/next/tests/next-router-tests.tsx b/types/next/tests/next-router-tests.tsx new file mode 100644 index 0000000000..38d091dcc2 --- /dev/null +++ b/types/next/tests/next-router-tests.tsx @@ -0,0 +1,50 @@ +import Router, * as r from 'next/router'; +import * as React from 'react'; +import * as qs from 'querystring'; + +Router.readyCallbacks.push(() => { console.log("I'll get called when the router initializes."); }); +Router.ready(() => { console.log("I'll get called immediately if the router initializes, or when it eventually does."); }); + +// Access readonly properties of the router. + +Object.keys(Router.components).forEach(key => { + const c = Router.components[key]; + c.err.isAnAny; + + return ; +}); + +function split(routeLike: string) { + routeLike.split('/').forEach(part => { + console.log("path part: ", part); + }); +} + +split(Router.pathname); +split(Router.asPath); +split(Router.asPath); + +const query = `?${qs.stringify(Router.query)}`; + +// Assign some callback methods. +Router.onAppUpdated = (nextRoute: string) => console.log(nextRoute); +Router.onRouteChangeStart = (url: string) => console.log("Route is starting to change.", url); +Router.onBeforeHistoryChange = (as: string) => console.log("History hasn't changed yet.", as); +Router.onRouteChangeComplete = (url: string) => console.log("Route chaneg is complete.", url); +Router.onRouteChangeError = (err: any, url: string) => console.log("Route is starting to change.", url, err); + +// Call methods on the router itself. +Router.reload('/route').then(() => console.log('route was reloaded')); +Router.back(); + +Router.push('/route').then((success: boolean) => console.log('route push success: ', success)); +Router.push('/route', '/asRoute').then((success: boolean) => console.log('route push success: ', success)); +Router.push('/route', '/asRoute', {shallow: false}).then((success: boolean) => console.log('route push success: ', success)); + +Router.replace('/route').then((success: boolean) => console.log('route replace success: ', success)); +Router.replace('/route', '/asRoute').then((success: boolean) => console.log('route replace success: ', success)); +Router.replace('/route', '/asRoute', {shallow: false}).then((success: boolean) => console.log('route replace success: ', success)); + +Router.prefetch('/route').then(Component => { + const element = (); +}); diff --git a/types/next/tsconfig.json b/types/next/tsconfig.json new file mode 100644 index 0000000000..7cd8fc1ee6 --- /dev/null +++ b/types/next/tsconfig.json @@ -0,0 +1,31 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6", + "dom" + ], + "target": "es6", + "jsx": "react", + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": false, + "baseUrl": "../", + "typeRoots": [ + "../" + ], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "next-tests.ts", + "tests/next-error-tests.tsx", + "tests/next-head-tests.tsx", + "tests/next-document-tests.tsx", + "tests/next-link-tests.tsx", + "tests/next-dynamic-tests.tsx", + "tests/next-router-tests.tsx" + ] +} diff --git a/types/next/tslint.json b/types/next/tslint.json new file mode 100644 index 0000000000..bf0deaa9f4 --- /dev/null +++ b/types/next/tslint.json @@ -0,0 +1,18 @@ +{ + "extends": "dtslint/dtslint.json", + "rules": { + // All of the different "export default" lines in the index.d.ts + // appear to be triggering this. Remove this when I know of a way + // to declare a default export across multiple packages. + "strict-export-declare-modifiers": false, + + // This is a pretty generic one to have to ignore, but it's because + // of the following error: + // `JSX element type '' does not have any construct or call signatures.` + // In all cases, the element's type is "React.ComponentType`, which is composed of either: + // - React.StatelessComponent, which has a call signature, or + // - React.ComponentClass, which as a construct signature. + // This seems like it might be a bug. + "expect": false + } +} From d12e78563cff4e53d2909cc6347b443eee9d0918 Mon Sep 17 00:00:00 2001 From: Drew Hays Date: Wed, 5 Jul 2017 11:28:43 -0700 Subject: [PATCH 2/6] follow pull request template --- types/next/tsconfig.json | 2 +- types/next/tslint.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/types/next/tsconfig.json b/types/next/tsconfig.json index 7cd8fc1ee6..b5476f610a 100644 --- a/types/next/tsconfig.json +++ b/types/next/tsconfig.json @@ -9,7 +9,7 @@ "jsx": "react", "noImplicitAny": true, "noImplicitThis": true, - "strictNullChecks": false, + "strictNullChecks": true, "baseUrl": "../", "typeRoots": [ "../" diff --git a/types/next/tslint.json b/types/next/tslint.json index bf0deaa9f4..71bde7f0b6 100644 --- a/types/next/tslint.json +++ b/types/next/tslint.json @@ -3,7 +3,7 @@ "rules": { // All of the different "export default" lines in the index.d.ts // appear to be triggering this. Remove this when I know of a way - // to declare a default export across multiple packages. + // to declare a default export across multiple package/subpackages. "strict-export-declare-modifiers": false, // This is a pretty generic one to have to ignore, but it's because From f7bf7985530eb341cb0abed3e1921ffe0de6aa2f Mon Sep 17 00:00:00 2001 From: Drew Hays Date: Wed, 5 Jul 2017 11:43:50 -0700 Subject: [PATCH 3/6] passes tests now --- types/next/index.d.ts | 2 +- types/next/{tests => test}/next-document-tests.tsx | 0 types/next/{tests => test}/next-dynamic-tests.tsx | 0 types/next/{tests => test}/next-error-tests.tsx | 0 types/next/{tests => test}/next-head-tests.tsx | 0 types/next/{tests => test}/next-link-tests.tsx | 0 types/next/{tests => test}/next-router-tests.tsx | 0 types/next/tsconfig.json | 12 ++++++------ types/next/tslint.json | 2 +- 9 files changed, 8 insertions(+), 8 deletions(-) rename types/next/{tests => test}/next-document-tests.tsx (100%) rename types/next/{tests => test}/next-dynamic-tests.tsx (100%) rename types/next/{tests => test}/next-error-tests.tsx (100%) rename types/next/{tests => test}/next-head-tests.tsx (100%) rename types/next/{tests => test}/next-link-tests.tsx (100%) rename types/next/{tests => test}/next-router-tests.tsx (100%) diff --git a/types/next/index.d.ts b/types/next/index.d.ts index ab57dd6241..51024ffc8f 100644 --- a/types/next/index.d.ts +++ b/types/next/index.d.ts @@ -1,4 +1,4 @@ -// Type definitions for next +// Type definitions for next 2.4 // Project: https://github.com/zeit/next.js // Definitions by: Drew Hays // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped diff --git a/types/next/tests/next-document-tests.tsx b/types/next/test/next-document-tests.tsx similarity index 100% rename from types/next/tests/next-document-tests.tsx rename to types/next/test/next-document-tests.tsx diff --git a/types/next/tests/next-dynamic-tests.tsx b/types/next/test/next-dynamic-tests.tsx similarity index 100% rename from types/next/tests/next-dynamic-tests.tsx rename to types/next/test/next-dynamic-tests.tsx diff --git a/types/next/tests/next-error-tests.tsx b/types/next/test/next-error-tests.tsx similarity index 100% rename from types/next/tests/next-error-tests.tsx rename to types/next/test/next-error-tests.tsx diff --git a/types/next/tests/next-head-tests.tsx b/types/next/test/next-head-tests.tsx similarity index 100% rename from types/next/tests/next-head-tests.tsx rename to types/next/test/next-head-tests.tsx diff --git a/types/next/tests/next-link-tests.tsx b/types/next/test/next-link-tests.tsx similarity index 100% rename from types/next/tests/next-link-tests.tsx rename to types/next/test/next-link-tests.tsx diff --git a/types/next/tests/next-router-tests.tsx b/types/next/test/next-router-tests.tsx similarity index 100% rename from types/next/tests/next-router-tests.tsx rename to types/next/test/next-router-tests.tsx diff --git a/types/next/tsconfig.json b/types/next/tsconfig.json index b5476f610a..0bcbd622d9 100644 --- a/types/next/tsconfig.json +++ b/types/next/tsconfig.json @@ -21,11 +21,11 @@ "files": [ "index.d.ts", "next-tests.ts", - "tests/next-error-tests.tsx", - "tests/next-head-tests.tsx", - "tests/next-document-tests.tsx", - "tests/next-link-tests.tsx", - "tests/next-dynamic-tests.tsx", - "tests/next-router-tests.tsx" + "test/next-error-tests.tsx", + "test/next-head-tests.tsx", + "test/next-document-tests.tsx", + "test/next-link-tests.tsx", + "test/next-dynamic-tests.tsx", + "test/next-router-tests.tsx" ] } diff --git a/types/next/tslint.json b/types/next/tslint.json index 71bde7f0b6..e4a2c8f088 100644 --- a/types/next/tslint.json +++ b/types/next/tslint.json @@ -1,5 +1,5 @@ { - "extends": "dtslint/dtslint.json", + "extends": "dtslint/dt.json", "rules": { // All of the different "export default" lines in the index.d.ts // appear to be triggering this. Remove this when I know of a way From e97722eb0ee7295e97697c2823b46a17ff404d9f Mon Sep 17 00:00:00 2001 From: Drew Hays Date: Wed, 5 Jul 2017 12:30:20 -0700 Subject: [PATCH 4/6] fix "expect" in tslint --- types/next/index.d.ts | 16 +++++++++------ types/next/next-tests.ts | 42 ++++++++++++++++++++-------------------- types/next/tslint.json | 11 +---------- 3 files changed, 32 insertions(+), 37 deletions(-) diff --git a/types/next/index.d.ts b/types/next/index.d.ts index 51024ffc8f..7f8eb6b18f 100644 --- a/types/next/index.d.ts +++ b/types/next/index.d.ts @@ -2,6 +2,7 @@ // Project: https://github.com/zeit/next.js // Definitions by: Drew Hays // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.3 /// @@ -106,11 +107,13 @@ declare module 'next/link' { } declare module 'next/dynamic' { + type ComponentType = React.StatelessComponent | typeof React.Component; + interface DynamicOptions { - loading?: React.ComponentType; + loading?: ComponentType; ssr?: boolean; - modules?(props: TCProps & TLProps): { [key: string]: Promise> }; - render?(props: TCProps & TLProps, modules: { [key: string]: React.ComponentType }): void; + modules?(props: TCProps & TLProps): { [key: string]: Promise> }; + render?(props: TCProps & TLProps, modules: { [key: string]: ComponentType }): void; } class SameLoopPromise extends Promise { @@ -119,11 +122,12 @@ declare module 'next/dynamic' { setError(value: any): void; runIfNeeded(): void; } - export default function(componentPromise: Promise>, options?: DynamicOptions): React.ComponentType; + export default function(componentPromise: Promise>, options?: DynamicOptions): ComponentType; } declare module 'next/router' { import * as url from 'url'; + type ComponentType = React.StatelessComponent | typeof React.Component; interface EventChangeOptions { shallow?: boolean; @@ -136,7 +140,7 @@ declare module 'next/router' { ready(cb: RouterCallback): void; // router properties - readonly components: { [key: string]: { Component: React.ComponentType, err: any } }; + readonly components: { [key: string]: { Component: ComponentType, err: any } }; readonly pathname: string; readonly route: string; readonly asPath: string; @@ -147,7 +151,7 @@ declare module 'next/router' { back(): void; push(url: string, as?: string, options?: EventChangeOptions): Promise; replace(url: string, as?: string, options?: EventChangeOptions): Promise; - prefetch(url: string): Promise>; + prefetch(url: string): Promise>; // router events onAppUpdated?(nextRoute: string): void; diff --git a/types/next/next-tests.ts b/types/next/next-tests.ts index 3c216d770d..bfa93bfff8 100644 --- a/types/next/next-tests.ts +++ b/types/next/next-tests.ts @@ -24,31 +24,31 @@ server.defineRoutes().then(voidFunc); server.start().then(voidFunc); const parsedUrl = url.parse('https://www.example.com'); -const req: http.IncomingMessage = null; -const res: http.ServerResponse = null; const handler = server.getRequestHandler(); -handler(req, res); -handler(req, res, parsedUrl).then(voidFunc); -server.run(req, res, parsedUrl).then(voidFunc); +function handle(req: http.IncomingMessage, res: http.ServerResponse) { + handler(req, res); + handler(req, res, parsedUrl).then(voidFunc); + server.run(req, res, parsedUrl).then(voidFunc); -server.render(req, res, '/path/to/resource', null, parsedUrl).then(voidFunc); -server.render(req, res, '/path/to/resource', { key: 'value' }, parsedUrl).then(voidFunc); -server.renderError(new Error(), req, res, '/path/to/resource', { key: 'value' }).then(voidFunc); -server.renderError('this can be an error, too!', req, res, '/path/to/resource', { key: 'value' }).then(voidFunc); -server.render404(req, res, parsedUrl).then(voidFunc); + server.render(req, res, '/path/to/resource', {}, parsedUrl).then(voidFunc); + server.render(req, res, '/path/to/resource', { key: 'value' }, parsedUrl).then(voidFunc); + server.renderError(new Error(), req, res, '/path/to/resource', { key: 'value' }).then(voidFunc); + server.renderError('this can be an error, too!', req, res, '/path/to/resource', { key: 'value' }).then(voidFunc); + server.render404(req, res, parsedUrl).then(voidFunc); -server.renderToHTML(req, res, '/path/to/resource', { foo: 'bar' }).then(x => x.split('\n')); -server.renderErrorToHTML(new Error(), req, res, '/path/to/resource', { foo: 'bar' }).then(x => x.split('\n')); + server.renderToHTML(req, res, '/path/to/resource', { foo: 'bar' }).then(x => x.split('\n')); + server.renderErrorToHTML(new Error(), req, res, '/path/to/resource', { foo: 'bar' }).then(x => x.split('\n')); -server.serveStatic(req, res, '/path/to/thing').then(voidFunc); + server.serveStatic(req, res, '/path/to/thing').then(voidFunc); -let b: boolean; -b = server.isServeableUrl('/path/to/thing'); -b = server.isInternalUrl(req); -b = server.handleBuildId('{buildId}', res); + let b: boolean; + b = server.isServeableUrl('/path/to/thing'); + b = server.isInternalUrl(req); + b = server.handleBuildId('{buildId}', res); -const s: string = server.readBuildId(); -server.getCompilationError('page', req, res).then(err => err.thisIsAnAny); -server.handleBuildHash('filename', 'hash', res); -server.send404(res); + const s: string = server.readBuildId(); + server.getCompilationError('page', req, res).then(err => err.thisIsAnAny); + server.handleBuildHash('filename', 'hash', res); + server.send404(res); +} diff --git a/types/next/tslint.json b/types/next/tslint.json index e4a2c8f088..98f9451050 100644 --- a/types/next/tslint.json +++ b/types/next/tslint.json @@ -4,15 +4,6 @@ // All of the different "export default" lines in the index.d.ts // appear to be triggering this. Remove this when I know of a way // to declare a default export across multiple package/subpackages. - "strict-export-declare-modifiers": false, - - // This is a pretty generic one to have to ignore, but it's because - // of the following error: - // `JSX element type '' does not have any construct or call signatures.` - // In all cases, the element's type is "React.ComponentType`, which is composed of either: - // - React.StatelessComponent, which has a call signature, or - // - React.ComponentClass, which as a construct signature. - // This seems like it might be a bug. - "expect": false + "strict-export-declare-modifiers": false } } From abf3f82b727b80fc73e20641f24af02e5451b2f8 Mon Sep 17 00:00:00 2001 From: Drew Hays Date: Thu, 6 Jul 2017 07:34:14 -0700 Subject: [PATCH 5/6] Use native React.ComponentType definition --- types/next/index.d.ts | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/types/next/index.d.ts b/types/next/index.d.ts index 7f8eb6b18f..436914fd5d 100644 --- a/types/next/index.d.ts +++ b/types/next/index.d.ts @@ -107,13 +107,11 @@ declare module 'next/link' { } declare module 'next/dynamic' { - type ComponentType = React.StatelessComponent | typeof React.Component; - interface DynamicOptions { - loading?: ComponentType; + loading?: React.ComponentType; ssr?: boolean; - modules?(props: TCProps & TLProps): { [key: string]: Promise> }; - render?(props: TCProps & TLProps, modules: { [key: string]: ComponentType }): void; + modules?(props: TCProps & TLProps): { [key: string]: Promise> }; + render?(props: TCProps & TLProps, modules: { [key: string]: React.ComponentType }): void; } class SameLoopPromise extends Promise { @@ -122,12 +120,11 @@ declare module 'next/dynamic' { setError(value: any): void; runIfNeeded(): void; } - export default function(componentPromise: Promise>, options?: DynamicOptions): ComponentType; + export default function(componentPromise: Promise>, options?: DynamicOptions): React.ComponentType; } declare module 'next/router' { import * as url from 'url'; - type ComponentType = React.StatelessComponent | typeof React.Component; interface EventChangeOptions { shallow?: boolean; @@ -140,7 +137,7 @@ declare module 'next/router' { ready(cb: RouterCallback): void; // router properties - readonly components: { [key: string]: { Component: ComponentType, err: any } }; + readonly components: { [key: string]: { Component: React.ComponentType, err: any } }; readonly pathname: string; readonly route: string; readonly asPath: string; @@ -151,7 +148,7 @@ declare module 'next/router' { back(): void; push(url: string, as?: string, options?: EventChangeOptions): Promise; replace(url: string, as?: string, options?: EventChangeOptions): Promise; - prefetch(url: string): Promise>; + prefetch(url: string): Promise>; // router events onAppUpdated?(nextRoute: string): void; From 001235c7763804d5d41eeb78011a45f1cf6b192c Mon Sep 17 00:00:00 2001 From: Drew Hays Date: Thu, 6 Jul 2017 08:39:19 -0700 Subject: [PATCH 6/6] clean up imports --- types/next/index.d.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/types/next/index.d.ts b/types/next/index.d.ts index 436914fd5d..ab6e3df6f5 100644 --- a/types/next/index.d.ts +++ b/types/next/index.d.ts @@ -69,11 +69,14 @@ declare module 'next/error' { declare module 'next/head' { import * as React from 'react'; + function defaultHead(): JSX.Element[]; export default class extends React.Component<{}, {}> {} } declare module 'next/document' { + import * as React from 'react'; + interface DocumentProps { __NEXT_DATA__?: any; dev?: boolean; @@ -91,6 +94,8 @@ declare module 'next/document' { declare module 'next/link' { import * as url from 'url'; + import * as React from 'react'; + type UrlLike = url.UrlObject | url.Url; interface LinkState { prefetch?: boolean; @@ -107,6 +112,8 @@ declare module 'next/link' { } declare module 'next/dynamic' { + import * as React from 'react'; + interface DynamicOptions { loading?: React.ComponentType; ssr?: boolean; @@ -124,7 +131,7 @@ declare module 'next/dynamic' { } declare module 'next/router' { - import * as url from 'url'; + import * as React from 'react'; interface EventChangeOptions { shallow?: boolean;