我正在使用 TypeScript 运行一个
express.js
应用程序。
每次我尝试处理request.query.foo
我都会收到以下错误:
Argument of type 'string | ParsedQs | string[] | ParsedQs[] | undefined' is not assignable to parameter of type 'string'.
Type 'undefined' is not assignable to type 'string'.
设置:
import { Request, Response, Router } from 'express';
const router = Router();
function getHandler(request: Request, response: Response) {
const { query } = request;
query.foo; // string | QueryString.ParsedQs | string[] | QueryString.ParsedQs[] | undefined
}
router.route('/')
.get(getHandler)
有没有正确的方法来键入
request.query
而无需转换?
解决方案是通过以下方式使用泛型。
const router = Router();
interface Foo {
foo: string;
}
function getHandler(request: Request<{}, {}, {}, Foo>, response: Response) {
const { query } = request;
query.foo;
}
router.route('/')
.get(getHandler)
Request
是一个泛型,它接受额外的定义:
interface Request<
P = core.ParamsDictionary,
ResBody = any,
ReqBody = any,
ReqQuery = core.Query,
Locals extends Record<string, any> = Record<string, any>
> extends core.Request<P, ResBody, ReqBody, ReqQuery, Locals> {}
interface RequestParams {}
interface ResponseBody {}
interface RequestBody {}
interface RequestQuery {
foo: string;
}
function getHandler(
request: Request<RequestParams, ResponseBody, RequestBody, RequestQuery>,
response: Response
) {
const { query } = request;
query.foo; // string
}
我喜欢在我的项目中使用以下方法。
const { url } = req.query;
if (typeof url !== "string") {
throw new ServerError("Query param 'url' has to be of type string", 400);
}
在检查类型之后,TypeScript 不会再抱怨这个范围了。
你可以这样做:-
interface Query {
param1:string;
param2:string;
};
function getHandler(request: Request, response: Response) {
const {param1,param2} = request.query as unknown as Query;
}
在我看来,更简单直接的方法是使用
StringConstructor
。欢迎在评论中提出这种方法在这种特殊情况下的任何缺点。
var 字符串:StringConstructor (价值?:任何)=>字符串 允许对文本字符串进行操作和格式化,以及确定和定位字符串中的子字符串。
import { Request, Response, Router } from 'express';
const router = Router();
function getHandler(request: Request, response: Response) {
const { foo } = request.query;
String(foo) // string
}
router.route('/').get(getHandler)
另一种可能的解决方案是使用Type Assertion:
function getHandler(request: Request, response: Response) {
const foo: string = request.query.foo as string
//do something with foo ...
}
对我来说最好的解决方案是首先转换为未知,然后是我的自定义界面。
interface CustomReqQuery {
foo: string;
bar: string;
}
function getHandler(req: Request, res: Response) {
const { foo, bar } = req.query as unknown as CustomReqQuery;
...
}
您应该使用实际的 JS 验证您的传入数据,而不是欺骗打字稿。
如果您只对处理
foo
是一个字符串感兴趣,那么在您从 query
中提取它时验证它是一个字符串。
function getHandler(request: Request, response: Response) {
const { query } = request;
const foo = (typeof query.foo === "string") ? query.foo : "";
// Want to error check?
if (foo === "") {
// Handle missing foo
}
// You now have a guaranteed string that typescript recognizes as a string
const myNumber = parseInt(foo); // No warnings here
}
只是一个想法:
import { Request, Response, Router } from 'express';
const router = Router();
interface HandlerRequest extends Request {
query: {
foo: string
}
}
function getHandler(request: HandlerRequest, response: Response) {
const {query: {foo}} = request;
if (foo) {
// Do something
} else {
// Otherwise...
}
}
router.route('/')
.get(getHandler)