microsoft / microsoft/TypeScript

Generic interface callback return type validation issue

Offen
#31,570 1 Kommentar 0 Reaktionen 1 zugewiesene Person Auf GitHub ansehen

@weswigham arbeitet bereits daran.

Seit 13.6.2019.

Needs Investigation
Vorherrschende Sprache
Go
Sterne
111k
Forks
14.4k
Ø Merge
1 T. 19 Std.
Gemergte PRs (30 T.)
117

Beschreibung

TypeScript Version: Version 3.5.0-dev.20190523

Search Terms:

union callback function flatMap overload

Code

interface I<A> {
  foo<B>(f: (a: A) => B | I<B>): I<B>;
}

class C<A> implements I<A> {
  constructor(readonly a: A) {}

  public foo<B>(f: (a: A) => B | C<B>): C<B> {
    const b: B | C<B> = f(this.a);
    if (b instanceof C) {
      return b;
    }

    return new C(b);
  }
}

Expected behavior:

I expect that the example passes the type check without any errors based on the following assumptions: C<A> implements I<A> thus the return of C<A>.foo including f: (a: A) => B | C<B> matches the types declared in I<A>.foo.

Side Note: The interface of foo is similar to Array.flatMap.

Actual behavior:

I get the following type error for C<A>.foo:

  Property 'foo' in type 'C<A>' is not assignable to the same property in base type 'I<A>'.
  Type '<B>(f: (a: A) => B | C<B>) => C<B>' is not assignable to type '<B>(f: (a: A) => B | I<B>) => I<B>'.
    Type 'C<B | I<B>>' is not assignable to type 'I<B>'.
      Types of property 'foo' are incompatible.
        Type '<B>(f: (a: B | I<B>) => B | C<B>) => C<B>' is not assignable to type '<B>(f: (a: B) => B | I<B>) => I<B>'.
          Types of parameters 'f' and 'f' are incompatible.
            Types of parameters 'a' and 'a' are incompatible.
              Type 'B | I<B>' is not assignable to type 'B'.
                Type 'I<B>' is not assignable to type 'B'.ts(2416)

I don

Playground Link:

https://codesandbox.io/s/hopeful-kirch-571v7?fontsize=14&module=%2Fsrc%2Findex.ts&view=editor

Related Issues:

Workaround:

One can workaround this issue using function overloading instead of a union return for the callback.

interface I<A> {
  foo<B>(f: (a: A) => B): I<B>;
  foo<B>(f: (a: A) => I<B>): I<B>;
}

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Bewertung

Dieses Issue wurde noch nicht bewertet.

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.