Typescript switch/case on string not maching when it should



I have a strange behavior on a switch statement that is supposed to check for possible values of a string.

I’m trying to develop a little parser and using TDD I managed to write (and test) a function that parses a single line at a time, resulting in the expected result for all my cases.

Now I’m developing a bigger function that parses a bunch of lines at once so what it does is essentially split these lines and call the function that parses one line at a time.

The strange behaviour happens when I’m checking a value:

parseLine(terrainLine: string): Terrain | Tile[] | Adventurer {
    const [lineType, ...lineData] = terrainLine.trim().split(' - ');

    switch (lineType) {
      case 'C':
        return Terrain.parseTerrain(lineData);

      case 'T':
        return Terrain.parseTreasures(lineData);

      case 'M':
        return [Terrain.parseMountain(lineData)];

      case 'A':
        return Terrain.parseAdventurer(lineData);

      default: {
        throw new TerrainError(
          `Unable to parse terrain tile with data: "${terrainLine}"`,
        );
      }
    }
  }

This function is tested and should be working properly with strings like 'C - 3 - 4' (this input was tested and passed) but when the following function makes a call, it does not work anymore and instead it triggers the default statement:

parse(terrainString: stirng): Terrain {
  const linesToParse = terrainString
      .split('n')
      .map((_) => _.trim()) // Get rid of spaces before and after interesting data
      .filter((_) => _.length && !_.startsWith('#')); // Get rid of empty lines && comments lines

  linesToParse.forEach((line) => {
      const parsed = Terrain.parseLine(line);
      // [...]
  }  

  // [...]
}

For reference, here are the tests I use:

// This one passes
it('should parse terrain lines right', () => {
  const terrainLine = 'C - 3 - 4';
  const expectedTerrain = new Terrain(3, 4);
  const parsed = parseLine(terrainLine);

  expect(parsed).toBeInstanceOf(Terrain);
  expect(parsed).toStrictEqual(expectedTerrain);
});

// This one doesn't
it('should accept valid terrains', () => {
  const terrainString = 'C​ - 3 - 4nM​ - 1 - 0nM​ - 2 - 1nT​ - 0 - 3 - 2nT​ - 1 - 3 - 3nA​ - Lara - 1 - 1 - S - AADADAGGAn';

  expect(() => {
    Terrain.parse(terrainString);
  }).not.toThrow();
});

Answer

As pointed out by @VLAZ, I had an invisible character of zero width when printed in my string which was causing this bug. Simply removing this character in the first place solved the problem.



Source: stackoverflow