简体   繁体   English

如何检查字符串以将其范围缩小到枚举中的字符串,并让TypeScript识别它(节点示例)?

[英]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.usersRestHandler类型的,这是一个在枚举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! 祝好运!

Link to code 链接到代码

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM