通用类型 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
之后,您应该不再看到您在问题中描述的编译器错误。
我正在尝试更新我的 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;
}
更新以回应您分享的
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
之后,您应该不再看到您在问题中描述的编译器错误。