带有严格空检查的RegExpMatchArray的打字稿类型定义

时间:2019-12-07 10:13:10

标签: typescript

问题

我在Typescript严格模式(严格的null检查)下使用可迭代对象(如果我的理解是正确的)遇到了一些麻烦。我想使用返回的'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(described here)定义新的类型。但是重新定义现有类型似乎很奇怪。我宁愿使用现有的逻辑,并对它执行自己的逻辑以使其通过。

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

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

1 个答案:

答案 0 :(得分:0)

您必须先检查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;
  }

结尾的!是所谓的non-null-assertion-operator,它明确表明在此处可空变量将包含一个值。如果访问matchLetter之前我们有type guard,打字稿就不要求这样做。但是我看到Typescript短毛绒仍然抱怨的情况。

由于您正在尝试将通用字符串分配给字符串枚举,所以direction上的错误已清除。我已经更改了上面的代码,以使用as强制转换来使短毛绒静音。

更改了direction分配后,您还需要在operations表达式的末尾进行更改:

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

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