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

Type inference not working for this particular use of Generics? #8952

Closed
coreh opened this issue Jun 3, 2016 · 4 comments
Closed

Type inference not working for this particular use of Generics? #8952

coreh opened this issue Jun 3, 2016 · 4 comments
Labels
By Design Deprecated - use "Working as Intended" or "Design Limitation" instead

Comments

@coreh
Copy link

coreh commented Jun 3, 2016

Hey there. I was experimenting with generics, and noticed that type inference didn't work as I expected for this particular case. I'm not entirely sure if this is an actual blind spot of the type inference mechanism, or if my declaration doesn't mean what I think it means. it's a bit similar to the “Curiously recurring template pattern” described on #5949, but isn't actually the CRTP, since there's no actual recursion involved. Thanks in advance for looking into this issue.

TypeScript Version:

1.8.10

Code

interface IFoo {
    foo: 'foo'; // Could be anything
}

interface IWrapped<I> {
    getObject(): I;
}

function unwrap<I, T extends IWrapped<I>>(x: T): I {
    return x.getObject();
}

let x: IWrapped<IFoo>/* = ... */;
let y = unwrap<IFoo, IWrapped<IFoo>>(x); // Type is IFoo (correct)
let z = unwrap(x); // Type is {} (incorrect?)

Expected behavior:

I expected the compiler to infer the type of z as being IFoo, like when using explicit generic parameters on y.

Actual behavior:

The compiler inferred the type of z as being {}.

@Arnavion
Copy link
Contributor

Arnavion commented Jun 3, 2016

Note that in this particular case you can write it with just one generic parameter and not hit the issue:

function unwrap<I>(x: IWrapped<I>): I {

but yes, it does look like a bug.

@DanielRosenwasser
Copy link
Member

DanielRosenwasser commented Jun 3, 2016

I think this is a symptom of the issue @vsiao pointed out in #7234.

@ahejlsberg ahejlsberg added the By Design Deprecated - use "Working as Intended" or "Design Limitation" instead label Jun 3, 2016
@ahejlsberg
Copy link
Member

This is by design. Inference only infers from the arguments passed to the function to the declared parameters, it does not factor in constraints. Constrains are simply checks that are performed after inference completes. In your example there's really no reason to have two type parameters (and you should never have type parameters you don't need), but there are indeed situations where you want to infer multiple type parameters from a single argument. #7234 is about those scenarios.

@coreh
Copy link
Author

coreh commented Jun 3, 2016

Hey there, thanks for looking into this!

In hindsight I have no idea why I didn't think of

function unwrap<I>(x: IWrapped<I>): I {

and instead went with the way more complicated construct.

Really excited about how powerful the type system is becoming. The & trick to infer multiple types on #7234 is also really cool.

@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
By Design Deprecated - use "Working as Intended" or "Design Limitation" instead
Projects
None yet
Development

No branches or pull requests

4 participants