Repository navigation
Bad type inference under --strictFunctionTypes #19576
Description
Activity
HerringtonDarkholme commented
on Oct 31, 2017 ContributorMore actionsI think this is an intended behavior.
compareNumberstype argument is covariant. This meansnumbermust be a supertype ofT. Empty array is typed initially asnever, a subtype of every other type. So, type checker should choosenever, sonumberis correctly typed covariantly.I would suggest annotate
mkList<number>That does feel like
neveris infecting the inference though. While it might be strictly sound it feels like resolution should only assignneverwhen there is no other suitable type.Reacted by Marin MarinovI think the main problem is that an unresolved contextually typed literal takes precedence. The array is not a variable reference, it's a literal. What surfaces is the presumably evolving implicit
never[]type, which is unexpected because it trumps user provided annotations.- addedSuggestionAn idea for TypeScriptAn idea for TypeScriptIn DiscussionNot yet reached consensusNot yet reached consensus
on Oct 31, 2017 One option here is to make no inferences form a fresh array literal. the parallel in an object literal case here would be:
declare function mkList<T>(items: { 0?: T }, comparator: Comparator<T>): LinkedList<T>; mkList({}, compareNumbers); // `number`, since no inferences are made from `{}`
Reacted by Marin Marinov and Aluan HaddadYes, I think that would be the best approach, but only if the array is empty.
- addedFixedA PR has been merged for this issueA PR has been merged for this issueand removedIn DiscussionNot yet reached consensusNot yet reached consensus
on Nov 5, 2017 - locked and limited conversation to collaborators
on Jun 14, 2018 - unlocked this conversation
on Aug 20, 2018 RyanCavanaugh commented
on Aug 20, 2018 MemberMore actionsExample of breaking soundness with an aliased
never[]type Comparator<T> = (x: T, y: T) => number; declare const compareStrings: Comparator<string>; declare const compareNumber: Comparator<number>; function makeArray<T1, T2>(arr1: T1[], arr2: T2[], c1: Comparator<T1>, c2: Comparator<T2>) { return { arr1, arr2 } } const arr: never[] = []; const res = makeArray(arr, arr, compareStrings, compareNumber); res.arr1.push(""); res.arr2.push(10);
TypeScript Version: 2.7.0-dev.20171029
Code
Actual behavior:
The implicit evolving
never[]type of the array literal is taking precedence, leading to unexpected results.