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

no type inference for generic function variable assignment ? #30048

Closed
connectdotz opened this issue Feb 22, 2019 · 4 comments
Closed

no type inference for generic function variable assignment ? #30048

connectdotz opened this issue Feb 22, 2019 · 4 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@connectdotz
Copy link

connectdotz commented Feb 22, 2019

TypeScript Version: 3.3.1

Search Terms: generic function assignment, generic type infer

Code

interface A<T> {
    foo: T;
}

const a: A<number> = { foo: 13 };

let getA: <T>() => A<T> = () => a; // <== error here

Expected behavior:
no compile error

Actual behavior:
compile error:

Type 'A<number>' is not assignable to type 'A<T>'.
  Type 'number' is not assignable to type 'T'.

Playground Link: here

Related Issues:

#17574
#26871

@jack-williams
Copy link
Collaborator

This is the right behaviour. The generic parameter T is rigid inside the definition of the function so it won’t pick up inferences. It’s better to think of T as a fixed, but unknown type; you can’t just assign a number to it.

If you want type inference you should leave type annotation off the declaration of the function.

@connectdotz
Copy link
Author

the idea is to let getA() to take any function so long as it's compliant to the generic interface. If I leave out the signature of getA(), it basically became "fixed" after the first assignment:

interface A<T> {
    foo: T;
}

const a: A<number> = { foo: 13 };

//let getA: <T>() => A<T> = () => a; 
let getA = () => a; 

const b: A<string> = { foo: "13" };
getA = () => b; // <== now error here

playground

this is a common pattern that a system assigned a default initial value/logic but later refined with actual implementation that are not known at compile time other than the generic interface they are conformed... maybe there are other ways to accomplish this?

@Nathan-Fenner
Copy link
Contributor

You want an existential type. You've written that getA has a universal (generic) type.

The easiest way would be to make getA: () => A<unknown>, because that's all that it could be used as. If the caller doesn't know what type they'll get out, then unknown is the best you can do (in most circumstances- if the parameter is used contravariantly you'd want never instead, I guess).

@RyanCavanaugh RyanCavanaugh added the Working as Intended The behavior described is the intended behavior; this is not a bug label Feb 26, 2019
@typescript-bot
Copy link
Collaborator

This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

5 participants