带有严格空值检查的RegExpMatchArray的Typescript类型定义

3

问题

在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 }));
});

我已经做了什么:

我阅读了几篇相关文章。

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

我还阅读了文章"How to avoid null check pollution in Javascript: use Optionals" (文章)。它指出,您可以使用提供检查值是否为null的方法的库。如果是,则使用错误消息处理它,然后返回其他内容。

不使用库,有没有办法呢?

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


1个回答

4

您必须先检查 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不应该要求这样做。但是我见过TypeScript仍然会抱怨的情况。

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 }));
  }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接