-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Closed
Labels
Fix AvailableA PR has been opened for this issueA PR has been opened for this issueFixedA PR has been merged for this issueA PR has been merged for this issueSuggestionAn idea for TypeScriptAn idea for TypeScript
Milestone
Description
Bug Report
π Search Terms
invariant generic, contravariant inference
Maybe related or perhaps because of the same design limitation mentioned in #44999
π Version & Regression Information
Tested with 4.3.5
β― Playground Link
π» Code
declare const d: <T, U>(_: { v: T, m: (t: T) => U, f: (u: U) => void }) => void
declare const a: "a"
declare const b: "b"
d({
v: a,
m: t => t,
f: u => {
let test1: "a" = u // Type 'unknown' is not assignable to type '"a"'.
}
})
d({
v: a,
m: (t: "a") => t,
f: u => {
let test2: "a" = u
}
})
d({
v: a,
m: _ => b,
f: u => {
let test3: "b" = u // Type 'unknown' is not assignable to type '"b"'
}
})
d({
v: a,
m: () => b,
f: u => {
let test4: "b" = u
}
})
π Actual behavior
In 1st and 3rd function call U
gets inferred to unknown
π Expected behavior
In 1st function call U
should get inferred to "a"
and in 3rd function call U
should get inferred to "b"
.
Clearly the contravariant position of U
in m
seems to be a problem because if we annotate it (as done in 2nd call) or omit it (as done in 4th call) it gets inferred to what is expect and there are no error.
A real world use case:
declare const branch:
<T, U extends T>(_: { test: T, if: (t: T) => t is U, then: (u: U) => void }) => void
declare const x: "a" | "b"
branch({
test: x,
if: (t): t is "a" => t === "a",
then: u => {
let test1: "a" = u // Type '"a" | "b"' is not assignable to type '"a"'
}
})
branch({
test: x,
if: (t: "a" | "b"): t is "a" => t === "a",
then: u => {
let test2: "a" = u // compiles
}
})
SlurpTheo
Metadata
Metadata
Assignees
Labels
Fix AvailableA PR has been opened for this issueA PR has been opened for this issueFixedA PR has been merged for this issueA PR has been merged for this issueSuggestionAn idea for TypeScriptAn idea for TypeScript