From 2010c4cda1097697390d981d63d31600d1fe9808 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 10 Nov 2017 08:30:59 -0800 Subject: [PATCH] Give lowest priority to inferences made from empty array literals --- src/compiler/checker.ts | 17 ++++++++++------- src/compiler/types.ts | 1 + 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a9aaa77fa74..fedc0c77c8f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10898,22 +10898,25 @@ namespace ts { // it as an inference candidate. Hopefully, a better candidate will come along that does // not contain anyFunctionType when we come back to this argument for its second round // of inference. Also, we exclude inferences for silentNeverType (which is used as a wildcard - // when constructing types from type parameters that had no inference candidates) and - // implicitNeverType (which is used as the element type for empty array literals). - if (source.flags & TypeFlags.ContainsAnyFunctionType || source === silentNeverType || source === implicitNeverType) { + // when constructing types from type parameters that had no inference candidates). + if (source.flags & TypeFlags.ContainsAnyFunctionType || source === silentNeverType) { return; } const inference = getInferenceInfoForType(target); if (inference) { if (!inference.isFixed) { - if (!inference.candidates || priority < inference.priority) { + // We give lowest priority to inferences of implicitNeverType (which is used as the + // element type for empty array literals). Thus, inferences from empty array literals + // only matter when no other inferences are made. + const p = priority | (source === implicitNeverType ? InferencePriority.NeverType : 0); + if (!inference.candidates || p < inference.priority) { inference.candidates = [source]; - inference.priority = priority; + inference.priority = p; } - else if (priority === inference.priority) { + else if (p === inference.priority) { inference.candidates.push(source); } - if (!(priority & InferencePriority.ReturnType) && target.flags & TypeFlags.TypeParameter && !isTypeParameterAtTopLevel(originalTarget, target)) { + if (!(p & InferencePriority.ReturnType) && target.flags & TypeFlags.TypeParameter && !isTypeParameterAtTopLevel(originalTarget, target)) { inference.topLevel = false; } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index bb62bead00b..3141e3f22d9 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3613,6 +3613,7 @@ namespace ts { NakedTypeVariable = 1 << 1, // Naked type variable in union or intersection type MappedType = 1 << 2, // Reverse inference for mapped type ReturnType = 1 << 3, // Inference made from return type of generic function + NeverType = 1 << 4, // Inference made from the never type } export interface InferenceInfo {