From 80c6d507792b9706617ca27e4fa5ec9e314db8a5 Mon Sep 17 00:00:00 2001 From: Harry Park Date: Thu, 26 Sep 2019 07:51:50 +1000 Subject: [PATCH] feat(koa): default state + default context (#37901) --- types/koa/index.d.ts | 30 +++++++++++-- types/koa/test/default.ts | 55 +++++++++++++++++++++++ types/koa/{koa-tests.ts => test/index.ts} | 0 types/koa/tsconfig.json | 3 +- 4 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 types/koa/test/default.ts rename types/koa/{koa-tests.ts => test/index.ts} (100%) diff --git a/types/koa/index.d.ts b/types/koa/index.d.ts index 4de24a8014..df6d5f82b9 100644 --- a/types/koa/index.d.ts +++ b/types/koa/index.d.ts @@ -3,6 +3,7 @@ // Definitions by: DavidCai1993 // jKey Lu // Brice Bernard +// harryparkdotio // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped // TypeScript Version: 2.3 @@ -431,7 +432,10 @@ declare interface ContextDelegatedResponse { flushHeaders(): void; } -declare class Application extends EventEmitter { +declare class Application< + StateT = Application.DefaultState, + CustomT = Application.DefaultContext +> extends EventEmitter { proxy: boolean; middleware: Application.Middleware[]; subdomainOffset: number; @@ -512,7 +516,7 @@ declare class Application extends EventEmitter { * * @api private */ - createContext( + createContext( req: IncomingMessage, res: ServerResponse, ): Application.ParameterizedContext; @@ -526,7 +530,22 @@ declare class Application extends EventEmitter { } declare namespace Application { - type Middleware = compose.Middleware>; + type DefaultStateExtends = any; + /** + * This interface can be augmented by users to add types to Koa's default state + */ + interface DefaultState extends DefaultStateExtends {} + + type DefaultContextExtends = {}; + /** + * This interface can be augmented by users to add types to Koa's default context + */ + interface DefaultContext extends DefaultContextExtends {} + + type Middleware< + StateT = DefaultState, + CustomT = DefaultContext + > = compose.Middleware>; interface BaseRequest extends ContextDelegatedRequest { /** @@ -701,7 +720,10 @@ declare namespace Application { respond?: boolean; } - type ParameterizedContext = ExtendableContext & { + type ParameterizedContext< + StateT = DefaultState, + CustomT = DefaultContext + > = ExtendableContext & { state: StateT; } & CustomT; diff --git a/types/koa/test/default.ts b/types/koa/test/default.ts new file mode 100644 index 0000000000..dfc4ca68cf --- /dev/null +++ b/types/koa/test/default.ts @@ -0,0 +1,55 @@ +import Koa = require('koa'); + +declare module 'koa' { + interface DefaultState { + stateProperty: boolean; + } + + interface DefaultContext { + logger: { + info: Function; + log: Function; + error: Function; + }; + } +} + +const app = new Koa(); + +app.context.logger = { + info: () => {}, + log: () => {}, + error: () => {}, +}; + +app.use((ctx, next) => { + ctx.state.stateProperty = false; + return next(); +}) + +app.use<{ a: boolean }>(async (ctx, next) => { + ctx.state.a = true; + ctx.state.b = ''; // undeclared property + await next(); +}); + +app.use((ctx, next) => { + const start: any = new Date(); + return next().then(() => { + const end: any = new Date(); + const ms = end - start; + ctx.logger.info(`${ctx.method} ${ctx.url} - ${ms}ms`); + ctx.user = {}; // undeclared property + ctx.assert(true, 404, 'Yep!'); + }); +}); + +// response +app.use(ctx => { + ctx.body = 'Hello World'; + ctx.body = ctx.URL.toString(); +}); + +app.listen(3000); + +const server = app.listen(); diff --git a/types/koa/koa-tests.ts b/types/koa/test/index.ts similarity index 100% rename from types/koa/koa-tests.ts rename to types/koa/test/index.ts diff --git a/types/koa/tsconfig.json b/types/koa/tsconfig.json index 5c4ba0f656..7c18151c2e 100644 --- a/types/koa/tsconfig.json +++ b/types/koa/tsconfig.json @@ -1,7 +1,8 @@ { "files": [ "index.d.ts", - "koa-tests.ts" + "test/index.ts", + "test/default.ts" ], "compilerOptions": { "module": "commonjs",