JSMonk / hegel

An advanced static type checker
https://hegel.js.org
MIT License
2.1k stars 59 forks source link

Inference doesn't work if a method returns an instance of the class that is instantiated with the method's type parameters #311

Open eilvelia opened 4 years ago

eilvelia commented 4 years ago

The type inference doesn't seem to work when a method returns an instance of the class whose type parameter depends on the method's type parameters. E.g:

class Functor<T> {
  map<U>(f : T => U) : Functor<U> { return new Functor<U>() }
}

const f1 = new Functor<number>()
const f2 = f1.map((x : number) : string => String(x)) // error

This errors with

Could not deduce type "Functor<string>" arising from the arguments (number) => string.
Please, provide type parameters for the call or provide default type value for parameters
of "<U>((number) => U) => Functor<U>" function.

It works correctly in Flow and TypeScript.

Can be fixed if f1.map<string>( is written manually.

Interestingly, if I replace

  map<U>(f : T => U) : Functor<U> { return new Functor<U>() }

with

  map<U>(f : T => U) { return new Functor<U>() }

then it will work, even though the inferred return type of map is still Functor<U>.

try hegel

anacierdem commented 3 years ago

A similar (not the same though) thing happens if we try to change a class generic based on method's type parameters;

class HttpRequest<D = unknown> {
  data: unknown = null;

  setData<T>(data: T): HttpRequest<T> {
    this.data = data;
    return this;
  }
}

const req = new HttpRequest();

const result = req.setData(5);

Here, result's type is unknown where we would expect it to be number. I'm not sure if this is related as there is no error thrown but the inference is off, we can create an additional issue if that'd be more appropriate.

JSMonk commented 3 years ago

Oh, right, it's another bug, related to inferencing this type. Thank you a lot guys (@anacierdem and @Bannerets) for providing this information.

JSMonk commented 3 years ago

Also, seems like all bugs like this will be fixed in the second version of Hegel.