Skip to content

Type inference cannot properly infer type for object literal returned from function #20008

Closed
@aczekajski

Description

@aczekajski

TypeScript Version: 2.6.0 and 2.7.0-dev.20171114

Code

declare namespace Module {
    class MyClass<T> {
        // template functions using Pick 
        foo<K extends keyof T>(o: Pick<T, K>): void;
        foo<K extends keyof T>(f: () => Pick<T, K>): void;

        // simple example without generics and Pick 
        bar(o: T): void;
        bar(f: () => T): void;  
    }
}

interface I {
    value: number;
}

class C extends Module.MyClass<I> {
    private fn() {
        this.foo({ nothing: 5 }); // ERROR | here it knows that "nothing" does not exist on I
        this.foo(() => ({ nothing: 5 })); // NO ERROR | but now it cannot infer that "nothing" does not exist on I
        this.foo<keyof I>(() => ({ nothing: 5 })); // ERROR | we explicitely provided a "keyof I" so K from line 6 is no longer inferred, and now it is able to say that the "value" property is missing, good 
        this.foo<keyof I>(() => ({ nothing: 5, value: 6 })); // NO ERROR | then we add missing "value" property to returned object and it still cannot see the additional "nothing", even though it was able to infer some information about the object

        // the same goes for the "bar" function, so it is not a problem of generics 
        this.bar({ nothing: 5 }); // ERROR | as desired
        this.bar(() => ({ nothing: 5 })); // ERROR | can see missing "value"
        this.bar(() => ({ nothing: 5, value: 6 })); // NO ERROR | cannot see unwanted "nothing"
    }
}

See the code in TypeScript playground.

Expected behavior:
Errors in all lines invoking foo and bar functions, saying that property nothing does not exist on type I or Pick<I, /* something */>.

Actual behavior:
TypeScript properly raises an error when foo/bar function gets an object literal that is incompatible with type I; It properly raises an error about property missing in object literal returned from function being passed to foo/bar when we explicitely specify which type we want to be returned, but cannot raise an error about nothing being incompatible with I when it's being returned from function (even with <keyof I> being explicitely specified for foo).

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions