【问题标题】:Generic type RouterContext requires 3 parameters - problem泛型 RouterContext 需要 3 个参数 - 问题
【发布时间】:2022-06-15 02:18:00
【问题描述】:

我正在尝试更新我的 deno 项目中模块的版本,但在更新它们后我收到以下错误,我不明白为什么会发生这种情况。有人遇到过这个问题吗?

错误:

* [错误]:通用类型 'RouterContext' 需要 1 到 3 个类型参数。 export const Register = async ({request, response}: RouterContext) => { ~~~~~~~~~~~~~ 在 file:///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'
    }
}

【问题讨论】:

    标签: deno oak


    【解决方案1】:

    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;
    }
    

    更新以响应您分享的your commentthe offsite code

    首先,感谢您提供reproducible example

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

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

    首先,最好将manage your dependencies 放在每个项目的中心位置(以避免冗长和重复的导入语句,并减少使用相同外部依赖项的不同、不兼容版本的可能性)。这可以通过从新模块 (./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
    
    

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

    【讨论】:

    • 旧版本没有问题..我不明白要添加什么参数?给建议
    • @Boris 我不知道:你还没有展示你的整个代码库,那么我怎么知道你的应用程序是如何工作的?
    • 我放了整个代码文件,希望有用。我仍在尝试修复它,但我没有取得进展
    • @Boris 不幸的是,这还不够。您必须提供minimal, reproducible example。 (最终,您需要使用generic type parameter for inference,但除非我能看到您如何使用中间件功能,否则我无法为您提供建议)。
    • 我提供了完整代码的链接codecollab.io/@proj/WeatherDatabaseSoup .. 我尝试了“推理”,但它不再起作用了
    【解决方案2】:

    只需将上下文传递给RouterContext。示例 -

    改变这一行: export const Login = async ({request, response, cookies}: RouterContext)

    到 export const Login = async ({request, response, cookies}: RouterContext"/login">)

    基本上,我们需要告诉RouterContext它试图注入依赖的路径是什么

    【讨论】:

      猜你喜欢
      • 2021-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多