首页 > 解决方案 > 在使用 koa 或 express 组合模块或组合中间件时,调试 typescript 错误的最佳方法是什么?

问题描述

我正在尝试使用 Koa 和 lowdb 建立一个简约的服务器;因为我也在打字稿上写所有东西,所以要满足每个节点包的类型有很多麻烦。

我首先分享我的 .tsconfig。注意:使用 moduleResolution: "node"

{
  "compilerOptions": {
    "target": "es2017",
    "module": "ESNext",
    "lib": [
      "es6","DOM"
    ] ,
    "allowJs": true,
    "outDir": "build",
    "rootDir": "src" ,
    "strict": true ,
    "noImplicitAny": true,
    "moduleResolution": "node",                 
    "esModuleInterop": true,
   
    /* Advanced Options */
    "resolveJsonModule": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }

确实设法设置了服务器,但是当我想有效地添加Multer时遇到了很多麻烦,从哪个库中选择来处理传入的数据。

在这篇文章中,有一个很好的讨论,最后我选择使用async-busboy [ ...] 可用的不同库似乎是最新的,当然,带来它自己的类型。

众所周知,koa 将所有内容都视为中间件,因此 async-await 上的包装器很有用!

import multer from '@koa/multer';
import koaStatic from 'koa-static';
import path from 'path';
import asyncBusboy from 'async-busboy';
import multer from '@koa/multer';
import koaStatic from 'koa-static';
import path from 'path';
import asyncBusboy from 'async-busboy';


const router = new Router();
const app = new Koa();

const corsOpt = {
  origin: /* process.env.CORS_ALLOW_ORIGIN ||  */ '*', // this work well to configure origin url in the server
  methods: ['GET', 'PUT', 'POST', 'DELETE', 'OPTIONS'], // to works well with web app, OPTIONS is required
  allowedHeaders: ['Content-Type', 'Authorization'], // allow json and token in the headers
};
app.use(cors(corsOpt));
app.use(logger());
app.use(koaBody());

app.use(koaStatic(__dirname + './static/uploads'));

const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, './uploads');
  },
  filename: function (req, file, cb) {
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9);
    cb(null, file.fieldname + '-' + uniqueSuffix + '.jpg');
  },
});
const upload = multer({ storage });

app.use(upload.any());

app.use(async function (ctx: KoaContext, next: () => any) {
  // ignore non-POSTs
  if ('POST' != ctx.method) return await next();
  const { files, fields } = await asyncBusboy(ctx.req);
  console.log(files);
  let err = await upload
    .single('file')(ctx as any, next)
    .then((res: any) => res)
    .catch((err: any) => err);
  if (err) {
    ctx.body = {
      code: 0,
      msg: err.message,
    };
  } else {
    ctx.body = {
      code: 1,
      data: files,
    };
  }
});

// add a route for uploading multiple files
router.post('/uploader', upload.fields([]), (ctx: KoaContext) => {
  console.log('ctx.request.files', ctx.request.files);
  console.log('ctx.files', ctx);
  console.log('ctx.request.body', ctx.request.body);
  ctx.body = 'done';
});

// REST OF CODE ...

app.use(router.routes()).use(router.allowedMethods());

app.listen(4040);
console.log('server running ... http://localhost:4040');

我仍在学习,或者说通过做这样的实验来破解所有打字稿的秘密。现在我确实有冲突,因为 mutler 正在做自己的表单数据(我假设通过从其他帖子中读取)到目前为止,这是通过 async-await 从 ctx.req.file 获取文件的解决方案,但我仍然在努力与类型。

当我确实设法让 multer 和 async-busboy 工作时,我不得不删除 koa-body,现在我再次引入这些打字稿错误。

No overload matches this call.
  Overload 1 of 4, '(name: string, path: string | RegExp, ...middleware: IMiddleware<any, {}>[]): Router<any, {}>', gave the following error.
    Argument of type '(ctx: KoaContext) => void' is not assignable to parameter of type 'string | RegExp'.
      Type '(ctx: KoaContext<any, any>) => void' is missing the following properties from type 'RegExp': exec, test, source, global, and 12 more.
  Overload 2 of 4, '(path: string | RegExp | (string | RegExp)[], ...middleware: IMiddleware<any, {}>[]): Router<any, {}>', gave the following error.
    Argument of type '(ctx: KoaContext) => void' is not assignable to parameter of type 'IMiddleware<any, {}>'.
      Types of parameters 'ctx' and 'context' are incompatible.
        Type 'ParameterizedContext<any, IRouterParamContext<any, {}>, any>' is not assignable to type 'KoaContext<any, any>'.

我也很难理解 ctx 和 context 之间的区别......

No overload matches this call.
  Overload 1 of 4, '(name: string, path: string | RegExp, ...middleware: IMiddleware<any, {}>[]): Router<any, {}>', gave the following error.
    Argument of type 'Middleware<DefaultState, DefaultContext, any>' is not assignable to parameter of type 'string | RegExp'.
      Type 'Middleware<DefaultState, DefaultContext, any>' is missing the following properties from type 'RegExp': exec, test, source, global, and 12 more.
  Overload 2 of 4, '(path: string | RegExp | (string | RegExp)[], ...middleware: IMiddleware<any, {}>[]): Router<any, {}>', gave the following error.
    Argument of type 'Middleware<DefaultState, DefaultContext, any>' is not assignable to parameter of type 'IMiddleware<any, {}>'.
      Types of parameters 'context' and 'context' are incompatible.
        Type 'ParameterizedContext<any, IRouterParamContext<any, {}>, any>' is not assignable to type 'ParameterizedContext<DefaultState, DefaultContext, any>'.
          Type 'ExtendableContext & { state: any; } & IRouterParamContext<any, {}> & { body: any; response: { body: any; }; }' is missing the following properties from type 'DefaultContext': file, files
  Overload 3 of 4, '(path: string | RegExp | (string | RegExp)[], middleware: Middleware<DefaultState, DefaultContext, any>, routeHandler: IMiddleware<any, DefaultContext>): Router<...>', gave the following error.
    Argument of type '(ctx: KoaContext) => void' is not assignable to parameter of type 'IMiddleware<any, DefaultContext>'.
      Types of parameters 'ctx' and 'context' are incompatible.
        Type 'ParameterizedContext<any, DefaultContext & IRouterParamContext<any, DefaultContext>, any>' is not assignable to type 'KoaContext<any, any>'.
          Types of property 'request' are incompatible.
            Type 'Request' is not assignable to type 'KoaRequest<any>'.
              Property 'body' is optional in type 'Request' but required in type 'KoaRequest<any>'.

你也可以在这里查看整个项目repo

对类型的任何帮助都会很棒。

希望它有助于使用带有 typescript 的 koa 进一步讨论。

标签: node.jstypescripthtml-parsingkoactx

解决方案


推荐阅读