microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
100.88k stars 12.47k forks source link

Type inference inconsistency with generic constraints #43804

Open evgenylink opened 3 years ago

evgenylink commented 3 years ago

Bug Report

🔎 Search Terms

🕗 Version & Regression Information

Tested on

⏯ Playground Link

Playground link

💻 Code

Following Generic Constraints

type Concatable<T> = {
    concat: (...xss: T[]) => T
};

export const concat = <T extends Concatable<T>>
    (xs: T, ...xss: T[] ): T => xs.concat( ...xss );

export const test_1 = concat([1, 2], [3, 4]);         // OK
export const test_2 = concat("foo" as string, "bar"); // OK
export const test_3 = concat<string>("foo", "bar");   // OK

// Expected: 'test_4: string'
// Got:      'test_4: Concatable<"foo" | "bar">'
export const test_4 = concat("foo", "bar");
// Error:                    ^^^^^
// Argument of type 'string' is not assignable to
// parameter of type 'Concatable<"foo" | "bar">'

🙁 Actual behavior

test_4: Concatable<"foo" | "bar">

TS leaks the constraint for type T into type T TS provides no good way to make Rust-like trait

🙂 Expected behavior

T, test_4, "foo" and "bar" all infer type string

RyanCavanaugh commented 3 years ago

@DanielRosenwasser any idea why the Concatable constraint creates a literal context? Seems wrong