首页 > 解决方案 > 带有严格空检查的 RegExpMatchArray 的打字稿类型定义

问题描述

问题

我在 Typescript 严格模式(严格的空检查)中的可迭代对象(如果我的理解是正确的)遇到了一些问题。我想使用'String.prototype.match()'的返回对象。

const matchLetter: RegExpMatchArray | null = points[0].match(/[a-zA-Z]/);

const direction: Tdirection = matchLetter[0];

// Two errors:
// 1. Object is possibly 'null'. ts(2531)
// 2. Type 'string' is not assignable to type 'Tdirection'. ts(2322)

我正在尝试做的事情:

// don't change RegExpMatchArray, it's from typescript lib.es5.d.ts
interface RegExpMatchArray extends Array<string> { index?: number; input?: string; }

// custom types
type Tlocation = { x: number; y: number };
type Tdirection = "R" | "U" | "L" | "D";

// demo data
const pathToPlot = [["R0", "R1", "R2"],["U0", "U1"],["L0"],["D0"]];

// demo operations
const operations = {
  R: (index: number, lastLocation: Tlocation) => { return { x: lastLocation.x + index, y: lastLocation.y }},
  U: (index: number, lastLocation: Tlocation) => { return { x: lastLocation.x + index, y: lastLocation.y }},
  L: (index: number, lastLocation: Tlocation) => { return { x: lastLocation.x - index, y: lastLocation.y }},
  D: (index: number, lastLocation: Tlocation) => { return { x: lastLocation.x, y: lastLocation.y - index }}
};

pathToPlot.forEach(points => {
  // In JS I did it like this: 
  // const direction = points[0].match(/[a-zA-Z]/)[0];

  // Typescript equivalent?
  const matchLetter: RegExpMatchArray | null = points[0].match(/[a-zA-Z]/);

  // This is giving errors: 
  const direction: Tdirection = matchLetter[0];

  // two errors:
  // 1. Object is possibly 'null'. ts(2531)
  // 2. Type 'string' is not assignable to type 'Tdirection'. ts(2322)

  console.log(operations[direction](1, { x: 0, y: 0 }));
});

实时代码示例:https ://codesandbox.io/s/reverent-thunder-s2wzn


到目前为止我做了什么:

我已经阅读了几篇关于这个问题的文章。

一个建议是为 RegExpArray 定义一个新类型(在此处描述)。但是重新定义现有类型似乎很奇怪。我宁愿使用现有的并围绕它执行我自己的逻辑以使其通过。

我还阅读了文章“如何避免 Javascript 中的 null 检查污染:使用 Optionals”(文章)。它指出您可以使用一个库,该库提供了一种检查值是否为空的方法。如果是这样,它会使用错误消息对其进行处理,然后返回其他内容。

不使用图书馆就没有办法吗?

标签: typescript

解决方案


您必须先检查 null :

  const matchLetter: RegExpMatchArray | null = points[0].match(/[a-zA-Z]/);

  if (matchLetter) {
    const direction: Tdirection = matchLetter[0];
  }

如果 Typescript 没有自动识别出该matchLetter值已经被检查过,那么让它显式:

  const matchLetter: RegExpMatchArray | null = points[0].match(/[a-zA-Z]/);

  if (matchLetter) {
    const direction: Tdirection = matchLetter![0] as Tdirection;
  }

尾随!是所谓的非空断言操作符,它明确表示可空变量此时将包含一个值。如果我们在访问matchLetter. 但我见过 Typescript linter 仍然抱怨的情况。

错误direction很明显,因为您试图将通用字符串分配给字符串枚举。我已经更改了上面的代码以使用as强制转换来使 linter 静音。

更改direction分配后,最后还需要更改operations表达式:

  var direction: Tdirection | undefined;
  if (matchLetter) {
    direction = matchLetter[0] as Tdirection;
  }

  if (direction) {
    console.log(operations[direction](1, { x: 0, y: 0 }));
  }

推荐阅读