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

Wrongly passed code using generics and string literal types #7472

Closed
tmcl opened this issue Mar 11, 2016 · 3 comments
Closed

Wrongly passed code using generics and string literal types #7472

tmcl opened this issue Mar 11, 2016 · 3 comments
Labels
Fixed A PR has been merged for this issue Question An issue which isn't directly actionable in code

Comments

@tmcl
Copy link

tmcl commented Mar 11, 2016

TypeScript Version:

1.8.7

compiled: tsc --noImplicitAny error.ts
(the behavior is exactly the same with or without --noImplictAny)

Code

// A self-contained demonstration of the problem follows...
type Greeting = "hello" | "goodbye"

const apply = <T extends string,R>(t: T, f: (t:T) => R): R => f(t)
const f1 = (a: Greeting) => console.log('greetings')
const f2 = (a: number) => console.log(3+a)

apply("hello", f1) /* 1. should be good. is good */
apply("helo", f1) /* 2a. should be error. is good */
apply<Greeting, void>("helo", f1) /* 2b. should be error. is error */

apply("hello", f2) /* 3. should be error. is error */
apply(3, f1) /* 4. should be error. is error */
apply(3, f2) /* 5. should be error. is error */

Expected behavior:
2-5 should have an error:

2 should have an error because "helo" is not a member of "hello"|"goodbye"
3 should have an error because "hello" is not a number
4 should have an error because 3 is not a member of "hello"|"goodbye" and because 3 is not a member of type which extends string
5 should have an error because 3 is not a member of a type which extends string, and because number does not extend string.

Actual behavior:
1, 2b, 3-5 are correct
2a passes typechecking even though it should be equivalent to 2b

@mhegazy
Copy link
Contributor

mhegazy commented Mar 11, 2016

@jesseschalken
Copy link
Contributor

@mhegazy Can you explain where function parameter bivariance comes into play here?

@jesseschalken
Copy link
Contributor

@tmcl explained it to me, the inferred generic parameters for 2a. are <string, void>, because string is the common type between "helo" and Greeting, and (s:Greeting) => void is compatible with (s:string) => void due to function parameter bivariance.

@mhegazy mhegazy closed this as completed Mar 29, 2016
@mhegazy mhegazy added the Question An issue which isn't directly actionable in code label Mar 29, 2016
@ahejlsberg ahejlsberg added the Fixed A PR has been merged for this issue label Sep 21, 2017
@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
Fixed A PR has been merged for this issue Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

4 participants