[英]How can I make a check on a string to narrow it down to the strings in an enum, and have TypeScript recognize it (node example)?
Using basic node.js, in http.createServer
I am taking the request
, and taking the path
from the request. 使用基本的node.js,在
http.createServer
我接受了request
,并从请求中获取了path
。 I have a router
object, keyed by paths, with values being handler functions. 我有一个
router
对象,以路径为键,其值为处理程序函数。
// index.ts
export interface DataObject {
queryStringObject: ParsedUrlQuery;
method: string;
headers: IncomingHttpHeaders;
payload: any;
}
export type HandlerCallback = (statusCode: number, payload?: Object) => any;
export type Handler = (data: DataObject, callback: HandlerCallback) => any;
interface Router {
ping: Handler;
users: Handler;
adminUsers: Handler;
tokens: Handler;
}
// Define request router
const router: Router = {
ping: handlers.ping,
users: handlers.users,
adminUsers: handlers.adminUsers,
tokens: handlers.tokens,
};
export enum RestMethods {
get = 'get',
post = 'post',
put = 'put',
delete = 'delete',
}
export type RestHandler = {
[method in RestMethods]: Handler;
};
Then, I have the file where handlers
is defined: 然后,我有了定义
handlers
的文件:
interface Handlers {
users: Handler;
adminUsers: Handler;
tokens: Handler;
notFound: Handler;
ping: Handler;
}
interface SubHandlers {
users: RestHandler;
adminUsers: RestHandler;
tokens: RestHandler;
}
export const handlers: Handlers = {
users: (data, callback) => {
const acceptableMethods = ['get', 'post', 'put', 'delete'];
if (acceptableMethods.indexOf(data.method) !== -1) {
subHandlers.users[data.method](data, callback);
}
},
(...)
I get a typescript
error on the line subhandlers.users[data.method]...
我在
subhandlers.users[data.method]...
行上subhandlers.users[data.method]...
typescript
错误subhandlers.users[data.method]...
Error:(62, 14) TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Router'.
错误:(62、14)TS7053:元素隐式具有“任意”类型,因为类型“字符串”的表达式不能用于索引类型“路由器”。 No index signature with a parameter of type 'string' was found on type 'Router'.
在“路由器”类型上找不到带有“字符串”类型参数的索引签名。
data.method
is a string
because DataObject
defines it that way (an incoming request could have anything in method
), and subhandlers.users
is of type RestHandler
, which is an object with keys in the enum RestMethods
. data.method
是一个string
因为DataObject
以此方式定义它(传入的请求可以在method
包含任何内容),并且subhandlers.users
是RestHandler
类型的,这是一个在枚举RestMethods
具有键的对象。 But I am doing the check acceptableMethods.indexOf(data.method) !== -1
... How can I make this check so that Typescript can realize that data.method has been restricted to only the strings that are in the enum? 但是我正在做检查
acceptableMethods.indexOf(data.method) !== -1
...我该如何进行检查,以便Typescript可以意识到data.method仅限于枚举中的字符串?
There are two issues here; 这里有两个问题; one is that
acceptableMethods
is inferred to be of type string[]
, whereas you want the compiler to keep track of the string literal values it contains; 一种是推断
acceptableMethods
的类型为string[]
,而您希望编译器跟踪其包含的字符串文字值; you can fix that easily enough with a const
assertion as in: 您可以使用
const
断言轻松地解决此问题,如下所示:
const acceptableMethods = ["get", "post", "put", "delete"] as const;
The second issue is that TypeScript does not understand or expect that, given an array array
of type T[]
and a value val
, checking array.indexOf(val) !== -1
should narrow val
to type T
. 第二个问题是TypeScript无法理解或期望给定类型为
T[]
的数组array
和值为val
,检查array.indexOf(val) !== -1
应该将val
缩小为T
类型。 Luckily you can get this behavior by making a user-defined type guard function : 幸运的是,您可以通过创建用户定义的类型防护函数来获得此行为:
function arrayIncludes<T>(
arr: ReadonlyArray<T>,
val: any
): val is T {
return arr.indexOf(val) !== -1;
}
Now you can use arrayIncludes()
in place of the indexOf
check, and it should work for you: 现在,您可以使用
arrayIncludes()
代替indexOf
检查,它应该可以为您工作:
export const handlers: Handlers = {
users: (data, callback) => {
const acceptableMethods = ["get", "post", "put", "delete"] as const;
if (arrayIncludes(acceptableMethods, data.method)) {
subHandlers.users[data.method](data, callback); // okay
}
}
};
Does that help? 有帮助吗? Good luck!
祝好运!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.