8000 Add union type checking to checkTypePredicate · ukyo/TypeScript@5d1b786 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5d1b786

Browse files
committed
Add union type checking to checkTypePredicate
And refactor checkSignatureDeclaration to call checkTypePredicate instead of duplicating its code.
1 parent 0806461 commit 5d1b786

File tree

1 file changed

+84
-66
lines changed

1 file changed

+84
-66
lines changed

src/compiler/checker.ts

Lines changed: 84 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -10963,6 +10963,87 @@ namespace ts {
1096310963
return -1;
1096410964
}
1096510965

10966+
function checkTypePredicate(node: TypePredicateNode) {
10967+
const parent = getTypePredicateParent(node);
10968+
if (!parent) {
10969+
error(node, Diagnostics.A_type_predicate_is_only_allowed_in_return_type_position_for_functions_and_methods);
10970+
return;
10971+
}
10972+
10973+
const typePredicate = getSignatureFromDeclaration(parent).typePredicate;
10974+
if (typePredicate.parameterIndex >= 0) {
10975+
if (parent.parameters[typePredicate.parameterIndex].dotDotDotToken) {
10976+
error(node.parameterName,
10977+
Diagnostics.A_type_predicate_cannot_reference_a_rest_parameter);
10978+
}
10979+
else {
10980+
checkTypeAssignableTo(typePredicate.type,
10981+
getTypeOfNode(parent.parameters[typePredicate.parameterIndex]),
10982+
node.type);
10983+
}
10984+
}
10985+
else if (node.parameterName) {
10986+
let hasReportedError = false;
10987+
for (var param of parent.parameters) {
10988+
if (hasReportedError) {
10989+
break;
10990+
}
10991+
if (param.name.kind === SyntaxKind.ObjectBindingPattern ||
10992+
param.name.kind === SyntaxKind.ArrayBindingPattern) {
10993+
10994+
(function checkBindingPattern(pattern: BindingPattern) {
10995+
for (const element of pattern.elements) {
10996+
if (element.name.kind === SyntaxKind.Identifier &&
10997+
(<Identifier>element.name).text === typePredicate.parameterName) {
10998+
10999+
error(node.parameterName,
11000+
Diagnostics.A_type_predicate_cannot_reference_element_0_in_a_binding_pattern,
11001+
typePredicate.parameterName);
11002+
hasReportedError = true;
11003+
break;
11004+
}
11005+
else if (element.name.kind === SyntaxKind.ArrayBindingPattern ||
11006+
element.name.kind === SyntaxKind.ObjectBindingPattern) {
11007+
11008+
checkBindingPattern(<BindingPattern>element.name);
11009+
}
11010+
}
11011+
})(<BindingPattern>param.name);
11012+
}
11013+
}
11014+
if (!hasReportedError) {
11015+
error(node.parameterName,
11016+
Diagnostics.Cannot_find_parameter_0,
11017+
typePredicate.parameterName);
11018+
}
11019+
}
11020+
11021+
if (node.type && node.type.kind === SyntaxKind.UnionType) {
11022+
for (const type of (<UnionTypeNode>node.type).types) {
11023+
if (type.kind === SyntaxKind.TypePredicate) {
11024+
checkTypePredicate(<TypePredicateNode>type);
11025+
}
11026+
}
11027+
}
11028+
}
11029+
11030+
function getTypePredicateParent(node: Node): SignatureDeclaration {
11031+
switch (node.parent.kind) {
11032+
case SyntaxKind.ArrowFunction:
11033+
case SyntaxKind.CallSignature:
11034+
case SyntaxKind.FunctionDeclaration:
11035+
case SyntaxKind.FunctionExpression:
11036+
case SyntaxKind.FunctionType:
11037+
case SyntaxKind.MethodDeclaration:
11038+
case SyntaxKind.MethodSignature:
11039+
const parent = <SignatureDeclaration>node.parent;
11040+
if(node === parent.type) {
11041+
return parent;
11042+
}
11043+
}
11044+
return undefined;
11045+
}
11046+
1096611047
function isInLegalTypePredicatePosition(node: Node): boolean {
1096711048
switch (node.parent.kind) {
1096811049
case SyntaxKind.ArrowFunction:
@@ -10993,66 +11074,9 @@ namespace ts {
1099311074

1099411075
forEach(node.parameters, checkParameter);
1099511076

10996-
if (node.type) {
10997-
if (node.type.kind === SyntaxKind.TypePredicate) {
10998-
const typePredicate = getSignatureFromDeclaration(node).typePredicate;
10999-
const typePredicateNode = <TypePredicateNode>node.type;
11000-
if (isInLegalTypePredicatePosition(typePredicateNode)) {
11001-
if (typePredicate.parameterIndex >= 0) {
11002-
if (node.parameters[typePredicate.parameterIndex].dotDotDotToken) {
11003-
error(typePredicateNode.parameterName,
11004-
Diagnostics.A_type_predicate_cannot_reference_a_rest_parameter);
11005-
}
11006-
else {
11007-
checkTypeAssignableTo(typePredicate.type,
11008-
getTypeOfNode(node.parameters[typePredicate.parameterIndex]),
11009-
typePredicateNode.type);
11010-
}
11011-
}
11012-
else if (typePredicateNode.parameterName) {
11013-
let hasReportedError = false;
11014-
for (var param of node.parameters) {
11015-
if (hasReportedError) {
11016-
break;
11017-
}
11018-
if (param.name.kind === SyntaxKind.ObjectBindingPattern ||
11019-
param.name.kind === SyntaxKind.ArrayBindingPattern) {
11020-
11021-
(function checkBindingPattern(pattern: BindingPattern) {
11022-
for (const element of pattern.elements) {
11023-
if (element.name.kind === SyntaxKind.Identifier &&
11024-
(<Identifier>element.name).text === typePredicate.parameterName) {
11025-
11026-
error(typePredicateNode.parameterName,
11027-
Diagnostics.A_type_predicate_cannot_reference_element_0_in_a_binding_pattern,
11028-
typePredicate.parameterName);
11029-
hasReportedError = true;
11030-
break;
11031-
}
11032-
else if (element.name.kind === SyntaxKind.ArrayBindingPattern ||
11033-
element.name.kind === SyntaxKind.ObjectBindingPattern) {
11034-
11035-
checkBindingPattern(<BindingPattern>element.name);
11036-
}
11037-
}
11038-
})(<BindingPattern>param.name);
11039-
}
11040-
}
11041-
if (!hasReportedError) {
11042-
error(typePredicateNode.parameterName,
11043-
Diagnostics.Cannot_find_parameter_0,
11044-
typePredicate.parameterName);
11045-
}
11046-
}
11047-
}
11048-
else {
11049-
error(typePredicateNode,
11050-
Diagnostics.A_type_predicate_is_only_allowed_in_return_type_position_for_functions_and_methods);
11051-
}
11052-
}
11053-
else {
11054-
checkSourceElement(node.type);
11055-
}
11077+
checkSourceElement(node.type);
11078+
if (node.type && node.type.kind === SyntaxKind.TypePredicate) {
11079+
1105611080
}
1105711081

1105811082
if (produceDiagnostics) {
@@ -14195,12 +14219,6 @@ namespace ts {
1419514219 74C1
}
1419614220
}
1419714221

14198-
function checkTypePredicate(node: TypePredicateNode) {
14199-
if (!isInLegalTypePredicatePosition(node)) {
14200-
error(node, Diagnostics.A_type_predicate_is_only_allowed_in_return_type_position_for_functions_and_methods);
14201-
}
14202-
}
14203-
1420414222
function checkSourceElement(node: Node): void {
1420514223
if (!node) {
1420614224
return;

0 commit comments

Comments
 (0)
0