通用类型 RouterContext 需要 3 个参数 - 问题

Generic type RouterContext requires 3 parameters - problem

我正在尝试更新我的 deno 项目中模块的版本,但更新后出现以下错误,我不明白为什么会这样。有人遇到过这个问题吗?

错误:

* [错误]:通用类型 'RouterContext<R, P, S>' 需要 1 到 3 个类型参数。 export const Register = async ({request, response}: RouterContext) => { ~~~~~~~~~~~~~ 在文件:///Users/X/Documents/DenoAPP/src/controller.ts:11:53

*

controller.ts:

import {RouterContext} from "https://deno.land/x/oak/mod.ts";
import {Bson} from "https://deno.land/x/mongo@v0.29.2/mod.ts";
import * as bcrypt from "https://deno.land/x/bcrypt/mod.ts";
import {create, verify} from "https://deno.land/x/djwt@v2.4/mod.ts"

import {db} from "./database/connection.ts";
import UserSchema from './schemas/user.ts';

const users = db.collection<UserSchema>("users");

export const Register = async ({request, response}: RouterContext) => {
    const {name, email, password} = await request.body().value;

    const _id = await users.insertOne({
        name,
        email,
        password: await bcrypt.hash(password)
    })

    const user = await users.findOne({_id});

    delete user.password;

    response.body = user;
}

export const Login = async ({request, response, cookies}: RouterContext) => {
    const {email, password} = await request.body().value;

    const user = await users.findOne({email});

    if (!user) {
        response.body = 404;
        response.body = {
            message: 'User not found!'
        };
        return;
    }

    if (!await bcrypt.compare(password, user.password)) {
        response.body = 401;
        response.body = {
            message: 'Incorrect password!'
        };
        return;
    }

    const jwt = await create({alg: "HS512", typ: "JWT"}, {_id: user._id}, "secret");

    cookies.set('jwt', jwt, {httpOnly: true});

    response.body = {
        message: 'success'
    };
}

export const Me = async ({response, cookies}: RouterContext) => {
    const jwt = cookies.get("jwt") || '';

    if (!jwt) {
        response.body = 401;
        response.body = {
            message: 'unauthenticated'
        };
        return;
    }

    const payload = await verify(jwt, "secret", "HS512");

    if (!payload) {
        response.body = 401;
        response.body = {
            message: 'unauthenticated'
        };
        return;
    }

    const {password, ...userData} = await users.findOne({_id: new Bson.ObjectId(payload._id)});

    response.body = userData;
}

export const Logout = async ({response, cookies}: RouterContext) => {
    cookies.delete('jwt');

    response.body = {
        message: 'success'
    }
}

RouterContext是泛型接口,必须至少提供第一个类型参数。因为您没有提供任何内容,所以您会收到编译器错误。

这是接口声明:

/** The context passed router middleware.  */
export interface RouterContext<
  R extends string,
  P extends RouteParams<R> = RouteParams<R>,
  // deno-lint-ignore no-explicit-any
  S extends State = Record<string, any>,
> extends Context<S> {
  /** When matching the route, an array of the capturing groups from the regular
   * expression. */
  captures: string[];

  /** The routes that were matched for this request. */
  matched?: Layer<R, P, S>[];

  /** Any parameters parsed from the route when matched. */
  params: P;

  /** A reference to the router instance. */
  router: Router;

  /** If the matched route has a `name`, the matched route name is provided
   * here. */
  routeName?: string;

  /** Overrides the matched path for future route middleware, when a
   * `routerPath` option is not defined on the `Router` options. */
  routerPath?: string;
}

更新以回应您分享的 and the offsite code

First, thanks for providing a reproducible example.

查看您的代码后,我发现还有其他不相关的类型问题,我不会尝试在此答案中解决。 (不过,随时欢迎您ask a new question。)

这些重构步骤应该可以帮助您解决问题中描述的编译器错误:

首先,最好 manage your dependencies 位于每个项目的中心位置(以避免冗长和重复的导入语句,并减少使用相同外部依赖项的不同、不兼容版本的可能性)。这可以通过 re-exporting 来自新模块 (./deps.ts) 的外部依赖项然后在所有其他模块中从该模块导入来实现:

./deps.ts:

export * as bcrypt from "https://deno.land/x/bcrypt@v0.3.0/mod.ts";

export {
  Application,
  Router,
  // type RouterContext, // This is removed in favor of the next one
  type RouterMiddleware, // This one is new: I included it for a later step in this answer
} from "https://deno.land/x/oak@v10.4.0/mod.ts";

export { Bson, MongoClient } from "https://deno.land/x/mongo@v0.29.2/mod.ts";

export { create, verify } from "https://deno.land/x/djwt@v2.4/mod.ts";

export { oakCors } from "https://deno.land/x/cors@v1.2.2/mod.ts";

然后,在其他需要外部依赖的模块中(例如./src/controller.ts):

import { bcrypt, Bson, create, type RouterContext, verify } from "../deps.ts";

// ...

现在,对于您询问的编译器问题:

需要最少重构的解决方案是在中间件函数表达式上使用 type annotation,而不是显式键入参数。在您的模块中 ./src/controllers.ts:

import {
  bcrypt,
  Bson,
  create,
  type RouterMiddleware, // You'll need this type import
  verify,
} from "../deps.ts";

// Skipping other module code: just focusing on the middleware...

// before
export const Register = async ({ request, response }: RouterContext) => {/* ... */}; /*
                                                      ~~~~~~~~~~~~~
Generic type 'RouterContext<R, P, S>' requires between 1 and 3 type arguments.deno-ts(2707) */

// after
export const Register: RouterMiddleware<string> = async (
  { request, response },
) => {/* ... */};

// and make the same change for every other midddleware which currently uses the `RouterContext` type

之后,您应该不再看到您在问题中描述的编译器错误。