Koa: How to define own ctx.state types

Created on 12 May 2019  ·  12Comments  ·  Source: koajs/koa

I used typescript to devloper koa app,I want to define my own type for ctx.state in global of app,but i don't know how to do.
QQ截图20190512150010

question

Most helpful comment

Sorry my last message was confusing, try this, should work:

interface State {
  userId: number;
}

interface Context {
  something: string;
} 

const app = new Koa<State, Context>().use(ctx => {
  ctx.state.userId // works
  ctx.something // works
});

I'm currently experimenting with TS and Koa here

All 12 comments

Look up generics in Typescript. StateT is a generic of ParametrizedContext.

@kibertoad Thks reply!but where should I define it?

@keyiis Inside route handler definition, I would think.

@kibertoad I has many route in different file,i hope define it somewhere that can be used globally

ctx.state only relative to this request, such as verifying login token, the middleware specified ctx.state.user_name='zhangsan';
In the request method can use
let user_name= ctx.state.user_name;

@ljphilp thks reply! in my app,every route has same object in ctx.state,so i want define a interface for ctx.state at app level.

@keyiis typings are provided by https://github.com/DefinitelyTyped/DefinitelyTyped, so this repo is not a correct place to ask such questions. You should ask questions on stackoverflow.

Regarding your issue. You can pass "global" state types when you initalize Koa app:

interface MyState {
   userId: number;
   deptId: number;
}
const app = new Koa<{MyState}, {}>();

@kroleg thks reply!but how to define global MyState to overwrite StateT?you code only work in the files that define it,but i has many route in different file.

@ljphilp thks reply! in my app,every route has same object in ctx.state,so i want define a interface for ctx.state at app level.

// 验证token中间件
const jwt = require('jsonwebtoken');

module.exports = function (){
  return function * ( next ) {
    // 执行中间件的操作
    let ctx = this;
    if (ctx.url !== '/apis/sysmgr/user/login' && ctx.request.headers['authorization']) {
      let auth_attr = ctx.request.headers['authorization'].split(' ');
      if(auth_attr[0] !=='Bearer' || auth_attr.length !== 2) {
        ctx.response.body = {
          msg: '授权错误,请重新登陆'
        };
        ctx.response.status = 401;
      }else{
        let token = auth_attr[1];
        let decoded = jwt.decode(token, process.env.JWT_SECRET);
        // 如果过期了就重新登录
        if (token && decoded.exp <= Date.now() / 1000) {
          ctx.response.body = {
            msg: '授权已经过期,请重新登陆'
          };
          ctx.response.status = 401;
        }else{
          ctx.state.user_name = decoded.user_name;
        }
      }
    }
    yield next
  }
};
© 2019 GitHub, Inc.

This is my solution that registers a middleware that assigns a value to ctx.state on each request, which can be used in the current request,hope that may help you,you can also refer to my project.

https://github.com/ljphilp/koa-restful

@ljphilp 谢谢你的回复,我在ctx.state里保存的数据不仅用于授权,在不同的router里需要读取ctx.state里的用户信息进行数据过滤,为保证团队成员都能规范的使用ctx.state里的信息,所以我需要定义一个interface来对ctx.state里的参数类型进行约束,我首先想到的是去改koa的types,但是这对以后升级koa会造成影响,所以我想是不是能自己定义一个全局的MyStateT类型去覆盖koa的StateT,这样就不用团队成员每次要使用ctx.state时,都要去再引入一遍MyStateT,比如
apiRouter.ts这是总的路由,负责把请求转发到不同的子路由,子路由定义在各自独立的文件中

apiRouter.use('/staff', JwtAuth2Rest, staffRouter.routes());
apiRouter.use('/role', JwtAuth2Rest, RoleRouter.routes());
apiRouter.use('/cat', JwtAuth2Rest, CatRouter.routes());
......

比如staffRouter.ts

ItemRouter.post('/list', async ctx => {
    let reqUser:MyStateT=ctx.state;
    ......
});
ItemRouter.post('/get', async ctx => {
    let reqUser:MyStateT=ctx.state;
    ......
});

上面代码中每次使用ctx.state时都要引入我自己定义的MyStateT,这样就比较麻烦

Sorry my last message was confusing, try this, should work:

interface State {
  userId: number;
}

interface Context {
  something: string;
} 

const app = new Koa<State, Context>().use(ctx => {
  ctx.state.userId // works
  ctx.something // works
});

I'm currently experimenting with TS and Koa here

Closing this as it seems to be answered. Please feel free to re-open if you still have issues with this.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ke1Del picture ke1Del  ·  3Comments

sibelius picture sibelius  ·  3Comments

edahlseng picture edahlseng  ·  3Comments

tvq picture tvq  ·  4Comments

rainesinternationaldev picture rainesinternationaldev  ·  5Comments