@@ -11187,7 +11187,53 @@ namespace ts {
1118711187 return -1;
1118811188 }
1118911189
11190- function isInLegalParameterTypePredicatePosition(node: Node): boolean {
11190+ function checkTypePredicate(node: TypePredicateNode) {
11191+ const parent = getTypePredicateParent(node);
11192+ if (!parent) {
11193+ return;
11194+ }
11195+ const returnType = getReturnTypeOfSignature(getSignatureFromDeclaration(parent));
11196+ if (!returnType || !(returnType.flags & TypeFlags.PredicateType)) {
11197+ return;
11198+ }
11199+ const { parameterName } = node;
11200+ if (parameterName.kind === SyntaxKind.ThisType) {
11201+ getTypeFromThisTypeNode(parameterName as ThisTypeNode);
11202+ }
11203+ else {
11204+ const typePredicate = <IdentifierTypePredicate>(<PredicateType>returnType).predicate;
11205+ if (typePredicate.parameterIndex >= 0) {
11206+ if (parent.parameters[typePredicate.parameterIndex].dotDotDotToken) {
11207+ error(parameterName,
11208+ Diagnostics.A_type_predicate_cannot_reference_a_rest_parameter);
11209+ }
11210+ else {
11211+ checkTypeAssignableTo(typePredicate.type,
11212+ getTypeOfNode(parent.parameters[typePredicate.parameterIndex]),
11213+ node.type);
11214+ }
11215+ }
11216+ else if (parameterName) {
11217+ let hasReportedError = false;
11218+ for (const { name } of parent.parameters) {
11219+ if ((name.kind === SyntaxKind.ObjectBindingPattern ||
11220+ name.kind === SyntaxKind.ArrayBindingPattern) &&
11221+ checkIfTypePredicateVariableIsDeclaredInBindingPattern(
11222+ <BindingPattern>name,
11223+ parameterName,
11224+ typePredicate.parameterName)) {
11225+ hasReportedError = true;
11226+ break;
11227+ }
11228+ }
11229+ if (!hasReportedError) {
11230+ error(node.parameterName, Diagnostics.Cannot_find_parameter_0, typePredicate.parameterName);
11231+ }
11232+ }
11233+ }
11234+ }
11235+
11236+ function getTypePredicateParent(node: Node): SignatureDeclaration {
1119111237 switch (node.parent.kind) {
1119211238 case SyntaxKind.ArrowFunction:
1119311239 case SyntaxKind.CallSignature:
@@ -11196,22 +11242,35 @@ namespace ts {
1119611242 case SyntaxKind.FunctionType:
1119711243 case SyntaxKind.MethodDeclaration:
1119811244 case SyntaxKind.MethodSignature:
11199- return node === (<SignatureDeclaration>node.parent).type;
11245+ const parent = <SignatureDeclaration>node.parent;
11246+ if (node === parent.type) {
11247+ return parent;
11248+ }
1120011249 }
11201- return false;
1120211250 }
1120311251
11204- function isInLegalThisTypePredicatePosition(node: Node): boolean {
11205- if (isInLegalParameterTypePredicatePosition(node)) {
11206- return true;
11207- }
11208- switch (node.parent.kind) {
11209- case SyntaxKind.PropertyDeclaration:
11210- case SyntaxKind.PropertySignature:
11211- case SyntaxKind.GetAccessor:
11212- return node === (node.parent as (PropertyDeclaration | GetAccessorDeclaration | PropertySignature)).type;
11252+ function checkIfTypePredicateVariableIsDeclaredInBindingPattern(
11253+ pattern: BindingPattern,
11254+ predicateVariableNode: Node,
11255+ predicateVariableName: string) {
11256+ for (const { name } of pattern.elements) {
11257+ if (name.kind === SyntaxKind.Identifier &&
11258+ (<Identifier>name).text === predicateVariableName) {
11259+ error(predicateVariableNode,
11260+ Diagnostics.A_type_predicate_cannot_reference_element_0_in_a_binding_pattern,
11261+ predicateVariableName);
11262+ return true;
11263+ }
11264+ else if (name.kind === SyntaxKind.ArrayBindingPattern ||
11265+ name.kind === SyntaxKind.ObjectBindingPattern) {
11266+ if (checkIfTypePredicateVariableIsDeclaredInBindingPattern(
11267+ <BindingPattern>name,
11268+ predicateVariableNode,
11269+ predicateVariableName)) {
11270+ return true;
11271+ }
11272+ }
1121311273 }
11214- return false;
1121511274 }
1121611275
1121711276 function checkSignatureDeclaration(node: SignatureDeclaration) {
@@ -11230,68 +11289,8 @@ namespace ts {
1123011289
1123111290 forEach(node.parameters, checkParameter);
1123211291
11233- if (node.type) {
11234- if (node.type.kind === SyntaxKind.TypePredicate) {
11235- const returnType = getReturnTypeOfSignature(getSignatureFromDeclaration(node));
11236- if (!returnType || !(returnType.flags & TypeFlags.PredicateType)) {
11237- return;
11238- }
11239- const typePredicate = (returnType as PredicateType).predicate;
11240- const typePredicateNode = node.type as TypePredicateNode;
11241- checkSourceElement(typePredicateNode);
11242- if (isIdentifierTypePredicate(typePredicate)) {
11243- if (typePredicate.parameterIndex >= 0) {
11244- if (node.parameters[typePredicate.parameterIndex].dotDotDotToken) {
11245- error(typePredicateNode.parameterName,
11246- Diagnostics.A_type_predicate_cannot_reference_a_rest_parameter);
11247- }
11248- else {
11249- checkTypeAssignableTo(typePredicate.type,
11250- getTypeOfNode(node.parameters[typePredicate.parameterIndex]),
11251- typePredicateNode.type);
11252- }
11253- }
11254- else if (typePredicateNode.parameterName) {
11255- let hasReportedError = false;
11256- for (var param of node.parameters) {
11257- if (hasReportedError) {
11258- break;
11259- }
11260- if (param.name.kind === SyntaxKind.ObjectBindingPattern ||
11261- param.name.kind === SyntaxKind.ArrayBindingPattern) {
11262-
11263- (function checkBindingPattern(pattern: BindingPattern) {
11264- for (const element of pattern.elements) {
11265- if (element.name.kind === SyntaxKind.Identifier &&
11266- (<Identifier>element.name).text === typePredicate.parameterName) {
11267-
11268- error(typePredicateNode.parameterName,
11269- Diagnostics.A_type_predicate_cannot_reference_element_0_in_a_binding_pattern,
11270- typePredicate.parameterName);
11271- hasReportedError = true;
11272- break;
11273- }
11274- else if (element.name.kind === SyntaxKind.ArrayBindingPattern ||
11275- element.name.kind === SyntaxKind.ObjectBindingPattern) {
11276-
11277- checkBindingPattern(<BindingPattern>element.name);
11278- }
11279- }
11280- })(<BindingPattern>param.name);
11281- }
11282- }
11283- if (!hasReportedError) {
11284- error(typePredicateNode.parameterName,
11285- Diagnostics.Cannot_find_parameter_0,
11286- typePredicate.parameterName);
11287- }
11288- }
11289- }
11290- }
11291- else {
11292- checkSourceElement(node.type);
11293- }
11294- }
11292+ checkSourceElement(node.type);
11293+
1129511294
1129611295 if (produceDiagnostics) {
1129711296 checkCollisionWithArgumentsInGeneratedCode(node);
@@ -14460,20 +14459,6 @@ namespace ts {
1446014459 }
1446114460 }
1446214461
14463- function checkTypePredicate(node: TypePredicateNode) {
14464- const { parameterName } = node;
14465- if (parameterName.kind === SyntaxKind.Identifier && !isInLegalParameterTypePredicatePosition(node)) {
14466- error(node, Diagnostics.A_type_predicate_is_only_allowed_in_return_type_position_for_functions_and_methods);
14467- }
14468- else if (parameterName.kind === SyntaxKind.ThisType) {
14469- if (!isInLegalThisTypePredicatePosition(node)) {
14470- error(node, Diagnostics.A_this_based_type_predicate_is_only_allowed_within_a_class_or_interface_s_members_get_accessors_or_return_type_positions_for_functions_and_methods);
14471- }
14472- else {
14473- getTypeFromThisTypeNode(parameterName as ThisTypeNode);
14474- }
14475- }
14476- }
1447714462
1447814463 function checkSourceElement(node: Node): void {
1447914464 if (!node) {
0 commit comments