Skip to content

Generic type parameter inferred as {} #8922

Closed
@wereHamster

Description

@wereHamster

TypeScript Version: 1.8.10, also tested with 1.9.0-dev.20160601-1.0 which behaves the same.

The following code should compile but produces an error. It is because the type of x is inferred as Either<{},number>. IOW, the type parameter E is made rigid when it should remain generic.

Code

interface Either<E,V> { e: E; v: V }

function pure<E,V>(v: V): Either<E,V> { return { e: undefined, v }; }
function fail<E,V>(e: E): I<E,V> { return { e, v: undefined }; }

function f(x: Either<string,number>) {}

const x = pure(1);
f(x); // <- error

A similar issue comes up when inferring the type of this constant:

const x = true ? pure(42) : fail("string");

TypeScript infers Either<{},number> | Either<string,{}> instead of the expected Either<string,number>.

To fix the first problem I could define pure to return Either<any,V>. But I don't want to do that, to allow TypeScript to automatically infer E from context. Such as in this case:

// The Monad `bind` function
function bind<E,A,B>(x: Either<E,A>, f: (a: A) => Either<E,B>): Either<E,B> {
    // Incomplete implementation of this function! Only for illustration purposes.
    throw new Error('Implement me!');
}

const x = bind(pure(42), n => fail("error"));

TypeScript infers x as Either<{},{}>, but it should be Either<string,V>. The E type parameter must be the same in both arguments as well as the return type of the whole function, and because the second argument (the function f) binds it to a string, it should remain a string.

If I change pure to return Either<any,V> and fail to return Either<E,any> then the type of x changes to Either<any,any>, which is not much better.

It would be nice to have an option like noImplicitAny to make it an error if TypeScript infers {} as a type parameter.

I could solve all these issues by always explicitly attaching the types to function calls and var/let/const statements. But that adds a lot of noise to the code, which is particularly annoying for simple cases where TypeScript should be able to infer the correct types.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Design LimitationConstraints of the existing architecture prevent this from being fixedToo ComplexAn issue which adding support for may be too complex for the value it adds

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions