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",