arcsecond icon indicating copy to clipboard operation
arcsecond copied to clipboard

Coroutine tutorial example doesn't type check

Open nvladimiroff opened this issue 3 years ago • 2 comments

When using Typescript (v4.8.2), the example from the second tutorial doesn't typecheck.

const {
  letters,
  coroutine,
  char
} = require('arcsecond');

const fullParser = coroutine(function* () {
  const firstWord = yield letters;

  yield char(' ');

  const secondWord = yield letters;

  return {
    type: 'word list',
    words: [
      firstWord.toUpperCase(),
      secondWord.toUpperCase()
    ]
  };
});
Object is possibly 'undefined'.

55       firstWord.toUpperCase(),
         ~~~~~~~~~

Object is possibly 'undefined'.

56       secondWord.toUpperCase()
         ~~~~~~~~~~

nvladimiroff avatar Sep 05 '22 05:09 nvladimiroff

Hey @nvladimiroff,

This is a known issue that occurs because of limitations of typing for generators in TypeScript. Because the generator is actually used by the coroutine function in a specific way, there is a disconnect between the type system and the kind of DSL that has been built up. This wouldn't be as much of a problem if the generator was only ever expected to yield one type of parser result (string, number, whatever), but it's meant to be generic.

The work around is to use something like this, which I may add to the library directly in a next release:

import {letters, coroutine, char, Parser} from 'arcsecond';

const yieldTyped = <T>(yielded: any, _parser: Parser<T>) => yielded as unknown as T;

const fullParser = coroutine(function* () {
  const firstWord = yieldTyped(yield letters, letters);

  yield char(' ');

  const secondWord = yieldTyped(yield letters, letters);

  return {
    type: 'word list',
    words: [
      firstWord.toUpperCase(),
      secondWord.toUpperCase()
    ]
  };
});

This is really just a comfortable forced-cast, and will not prevent you from specifying a different parser as the second argument. Not perfect, but can be useful if you're willing to accept a balance between type-safety and utility.

francisrstokes avatar Sep 06 '22 08:09 francisrstokes

Gotcha, that makes sense.

Would an approach like what typed-redux-saga did work for arcsecond too? It looks like that tries to fix a similar problem for redux-saga. (but feel free to let me know if I'm wrong there!)

nvladimiroff avatar Sep 07 '22 02:09 nvladimiroff

This has found a nice solution in the form of #90, and will be in the next major version.

francisrstokes avatar Sep 23 '22 18:09 francisrstokes