dart2jsのコンパイルエラー解決方法(same class with different type arguments)

Dartでコードを書いていると稀にdart VMでは動くのにdart2jsでコンパイルが通らないことがある。 例えば下記のようなコード。

abstract class Parser<T> {
  T parse(String input);
}

class NumParser implements Parser<num> {
  num parse(String input) => num.parse(input);
}

// [IntParser]が2つの型を`implements`している
class IntParser implements NumParser, Parser<int> {
  @override int parse(String key) => num.parse(key).toInt();
}

main() {
  for (NumParser parser in [new NumParser(), new IntParser()]) {
    num n = parser.parse('3.14');
    print(n); // 1回目は'3.14'、2回目は'3'を出力する
  }
}

IntParserParser<int>の要件を満たしているから必然的にParser<num>の要件も満たす。
IntParserNumParserimplementsすることは言語仕様的には何も問題もないコードであるが、dart2jsは次のようなエラーを吐く。

parse_test.dart:9:1:
Error: Dart2js does not currently support inheritance of the same class with different type arguments: Both Parser<int> and Parser<num> are supertypes of IntParser.
class IntParser implements NumParser, Parser<int> {
^^^^^
Error: Compilation failed.

上記の例の場合は運がいいことに、クラス定義を次のように書き換えることでコンパイルエラーを解決できる。この方法であれば他の既存のコードを書き換える必要がない。

class NumParser<N extends num> implements Parser<N> {
  N parse(String input) => num.parse(input);
}

class IntParser implements NumParser<int> {
  @override int parse(String key) => num.parse(key).toInt();
}

もし運が悪いことにNumParserがすでに型引数を持っていた場合、他の既存コードにも影響がでてしまう可能性がある。
そのときは…その時になってから解決策を考えることにする。