profile
viewpoint

Ask questions[Proposal] Better type support

Since this project followed koa's design, it has the same problem on types. Here I have a proposal to bring better type support for middleware.

The problem is that you cannot extend Application's type parameter when applying middlewares(which attach extra properties to ctx.state) on it. For example:

const app = new Application()

app.use(ctx => {
    ctx.state.username = 'foo'
}).use(ctx => {
    // not type safe for username
    ctx.state.username
})

My idea is we can change the prototype of use like this:

class Application<S>{
  use<NS extends {} = S>(middleware: Middleware<NS, Context<NS>>): Application<NS extends S ? NS : (S & NS)>
}

So we can happily write middleware with type checking:

// when need to extend context type, declare only what you want to attach
app.use((ctx: Context<{ name: string }>) => {
  ctx.state.name = 'foo'
  // I'm not including next here for simplification 
})
// extend again
.use((ctx: Context<{ id: string }>) => {
  ctx.state.id = 'id'
})
// context type is by default according to last middleware
.use((ctx) => {
  // ctx has a default type
  ctx.state.id = 'id'
  ctx.state.name = 'name'
})

It's not hard to do so if we don't support applying multiple middleware by one use call(which should be a rare use case).

And it's a little complicated for Router, we also want Router to have same context type as Application, so the Router instance must be created by a Application instance, so its type parameter can be inherited.

Application<S> {
  createRouter(): Router<S>
}

If you're good with this, I'll be working on it and send a pull request. Or please reply if have any comments.

oakserver/oak

Answer questions kitsonk

Closed via 5e591f91a5af410a83a779a9e3314a2d7bb40545

useful!

Related questions

No questions were found.
Github User Rank List