Skip to content

Generic functions that have a function as a parameter expand inferred type instead of narrowing #26127

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
nomcopter opened this issue Aug 1, 2018 · 4 comments
Assignees
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue

Comments

@nomcopter
Copy link

TypeScript Version: [email protected]

Search Terms: Generic Type Inference Function Parameter Union

Code

interface Foo {
    foo: number;
}

declare function acceptUnion(foo: Foo | number): void;
declare var foo: Foo;

declare function erroneouslyExpands<T>(value: T, func: (t: T) => void): T;

 // Errors, TS infers the result as `Foo | number`
const test: Foo = erroneouslyExpands(foo, acceptUnion);

Note: This case is common when passing comparators into functions.

Expected behavior:

T should be inferred as Foo.

Actual behavior:

T is expanded based on what func accepts.

Playground Link: https://www.typescriptlang.org/play/index.html#src=interface%20Foo%20%7B%0A%20%20%20%20foo%3A%20number%3B%0A%7D%0A%0Adeclare%20function%20acceptUnion(foo%3A%20Foo%20%7C%20number)%3A%20void%3B%0Adeclare%20var%20foo%3A%20Foo%3B%0A%0Adeclare%20function%20erroneouslyExpands%3CT%3E(value%3A%20T%2C%20func%3A%20(t%3A%20T)%20%3D%3E%20void)%3A%20T%3B%0A%0Aconst%20test%3A%20Foo%20%3D%20erroneouslyExpands(foo%2C%20acceptUnion)%3B%0A

Related Issues:

@RyanCavanaugh
Copy link
Member

See #14829

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Aug 1, 2018
@ahejlsberg
Copy link
Member

In --strictFunctionTypes mode we should definitely infer just Foo, so I'm changing this back to a bug.

@ahejlsberg ahejlsberg added Bug A bug in TypeScript and removed Duplicate An existing issue was already created labels Aug 20, 2018
@ahejlsberg
Copy link
Member

However, fixing this causes #19576 to again break. I seems that having #19576 be an error is the lesser of two evils, but it would be nice to somehow keep around contra-variant inferences when the only co-variant inference we have is a never resulting from a freshly created array literal.

@ahejlsberg ahejlsberg self-assigned this Aug 20, 2018
@ahejlsberg ahejlsberg added this to the TypeScript 3.1 milestone Aug 20, 2018
@ahejlsberg ahejlsberg added the Fixed A PR has been merged for this issue label Aug 20, 2018
@thw0rted
Copy link

thw0rted commented Jul 3, 2019

I'm still having issues with this, I think. You can see the error on this Playground example. Note that bad gives a compiler error.

The problem that lead me here is that const s: BehaviorSubject<number[]> = new BehaviorSubject([]); is an error if I turn strictFunctionTypes on. ("Type 'BehaviorSubject<never[]>' is not assignable to type 'BehaviorSubject<number[]>'.") I can't imagine that we really want everybody to have to write new BehaviorSubject([] as number[]) all over the place. Am I missing something?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue
Projects
None yet
Development

No branches or pull requests

4 participants