Skip to content
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

Generics inferred as {} versus void #8554

Closed
kitsonk opened this issue May 11, 2016 · 3 comments
Closed

Generics inferred as {} versus void #8554

kitsonk opened this issue May 11, 2016 · 3 comments

Comments

@kitsonk
Copy link
Contributor

kitsonk commented May 11, 2016

TypeScript Version:

any but using 1.9.0-dev.20160511

Code

function foo<T>(executor: (resolve: (value?: T) => void) => void): () => T {
    return () => {
        return <T> {};
    };
};

const result1 = foo((resolve) => {
    resolve();
});

const result2 = foo<void>((resolve) => {
    resolve();
});

result1; // type is `() => {}`
result2; // type is `() => void`

Expected behavior:

When generics are contextually inferred with optional parameters, they result in a void type.

Actual behavior:

When generics are contextually inferred, they result in a {} type.

This in particular becomes a problem with Promise when:

const promise = new Promise((resolve) => {
    resolve();
});

promise; // type is Promise<{}>
@jeffreymorlan
Copy link
Contributor

That would require TypeScript to infer the type of the resolve argument from the way it's used inside the function, which is the opposite direction of usual type inference. Could get complicated.

@kitsonk
Copy link
Contributor Author

kitsonk commented May 12, 2016

Hmmm... You are right, I had incorrectly assumed for some reason that:

const promise = new Promise((resolve) => {
    resolve('foo');
});

promise; // expected Promise<string> got Promise<{}>

Although:

const promise1 = new Promise((resolve) => {
    resolve('bar');
});

const promise2 = promise1
    .then(() => 'foo');

promise1; // type of Promise<{}>
promise2; // type of Promise<string>

Which led to my confusion of thinking the executor was able to resolve the type.

As far as the "opposite direction" types are often inferred from their call site:

function foo<T>(value: T): T { return; }

const result = foo('bar');

result; // type of string

And the type is "knowable" via static analysis of the code, just like a return type is knowable, which is how the type is inferred from a .then() statement.

@kitsonk
Copy link
Contributor Author

kitsonk commented May 14, 2016

Arghhh, sorry... This is #5254 where I was actually saying it was difficult for TypeScript to do... Obviously, while potentially a challenge for TypeScript, it is counter intuitive.

@kitsonk kitsonk closed this as completed May 14, 2016
@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants