Wrongly passed code using generics and string literal types · Issue #7472 · microsoft/TypeScript (original) (raw)

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