diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 98cd87923761e..73b29f5115442 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16531,36 +16531,31 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getUnionOrIntersectionTypePredicate(signatures: readonly Signature[], kind: TypeFlags | undefined): TypePredicate | undefined { - let first: TypePredicate | undefined; + let last: TypePredicate | undefined; const types: Type[] = []; for (const sig of signatures) { const pred = getTypePredicateOfSignature(sig); - if (!pred || pred.kind === TypePredicateKind.AssertsThis || pred.kind === TypePredicateKind.AssertsIdentifier) { - if (kind !== TypeFlags.Intersection) { - continue; - } - else { - return; // intersections demand all members be type predicates for the result to have a predicate - } - } - - if (first) { - if (!typePredicateKindsMatch(first, pred)) { - // No common type predicate. + if (pred) { + // Constituent type predicates must all have matching kinds. We don't create composite type predicates for assertions. + if (pred.kind !== TypePredicateKind.This && pred.kind !== TypePredicateKind.Identifier || last && !typePredicateKindsMatch(last, pred)) { return undefined; } + last = pred; + types.push(pred.type); } else { - first = pred; + // In composite union signatures we permit and ignore signatures with a return type `false`. + const returnType = kind !== TypeFlags.Intersection ? getReturnTypeOfSignature(sig) : undefined; + if (returnType !== falseType && returnType !== regularFalseType) { + return undefined; + } } - types.push(pred.type); } - if (!first) { - // No signatures had a type predicate. + if (!last) { return undefined; } const compositeType = getUnionOrIntersectionType(types, kind); - return createTypePredicate(first.kind, first.parameterName, first.parameterIndex, compositeType); + return createTypePredicate(last.kind, last.parameterName, last.parameterIndex, compositeType); } function typePredicateKindsMatch(a: TypePredicate, b: TypePredicate): boolean {