代码之家  ›  专栏  ›  技术社区  ›  Remi

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

  •  0
  • Remi  · 技术社区  · 6 年前

    问题

    在Typescript strict模式(严格的空检查)中,iterable对象(如果我的理解正确)有一些问题。我想使用“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中的空检查污染:使用Optionals”( article ). 它声明您可以使用提供方法的库来检查值是否为空。如果是这样,它会用一条错误消息来处理它,然后它会返回一些其他信息。

    有没有办法不用图书馆?

    1 回复  |  直到 6 年前
        1
  •  0
  •   Mike Lischke    6 年前

    必须先检查空值:

      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 这使得可以为空的变量此时将包含一个值。如果我们有 type guard 在进入之前 火柴信 . 但我也看到过这样的案例,打字机的线头还在抱怨。

    上的错误 direction 很清楚,因为您正在尝试将泛型字符串分配给字符串枚举。我把上面的代码改成了 as 铸造以使绒布安静下来。

    一旦你改变了 方向 任务,您还需要更改 operations 结尾处的表达式:

      var direction: Tdirection | undefined;
      if (matchLetter) {
        direction = matchLetter[0] as Tdirection;
      }
    
      if (direction) {
        console.log(operations[direction](1, { x: 0, y: 0 }));
      }
    
    推荐文章