Skip to content

Commit 4a14e61

Browse files
committed
Addresses CR feedback
1 parent 487dff5 commit 4a14e61

10 files changed

+192
-75
lines changed

src/compiler/checker.ts

+31-10
Original file line numberDiff line numberDiff line change
@@ -8601,15 +8601,16 @@ module ts {
86018601
}
86028602
}
86038603

8604-
function isInATypePredicateCompatiblePosition(node: Node): boolean {
8604+
function isInLegalTypePredicatePosition(node: Node): boolean {
86058605
switch (node.parent.kind) {
86068606
case SyntaxKind.ArrowFunction:
8607+
case SyntaxKind.CallSignature:
86078608
case SyntaxKind.FunctionDeclaration:
86088609
case SyntaxKind.FunctionExpression:
86098610
case SyntaxKind.FunctionType:
86108611
case SyntaxKind.MethodDeclaration:
86118612
case SyntaxKind.MethodSignature:
8612-
return true;
8613+
return node === (<SignatureDeclaration>node.parent).type;
86138614
}
86148615
return false;
86158616
}
@@ -8634,11 +8635,11 @@ module ts {
86348635
if (node.type.kind === SyntaxKind.TypePredicate) {
86358636
let typePredicate = getSignatureFromDeclaration(node).typePredicate;
86368637
let typePredicateNode = <TypePredicateNode>node.type;
8637-
if (isInATypePredicateCompatiblePosition(typePredicateNode)) {
8638+
if (isInLegalTypePredicatePosition(typePredicateNode)) {
86388639
if (typePredicate.parameterIndex >= 0) {
86398640
if (node.parameters[typePredicate.parameterIndex].dotDotDotToken) {
86408641
error(typePredicateNode.parameterName,
8641-
Diagnostics.Type_predicate_cannot_reference_a_spread_parameter);
8642+
Diagnostics.Type_predicate_cannot_reference_a_rest_parameter);
86428643
}
86438644
else {
86448645
checkTypeAssignableTo(typePredicate.type,
@@ -8647,14 +8648,34 @@ module ts {
86478648
}
86488649
}
86498650
else if (typePredicateNode.parameterName) {
8650-
error(typePredicateNode.parameterName,
8651-
Diagnostics.Cannot_find_parameter_0,
8652-
typePredicate.parameterName);
8651+
let hasReportedError = false;
8652+
outer: for (let param of node.parameters) {
8653+
if (param.name.kind === SyntaxKind.ObjectBindingPattern ||
8654+
param.name.kind === SyntaxKind.ArrayBindingPattern) {
8655+
8656+
for (let element of (<BindingPattern>param.name).elements) {
8657+
if (element.name.kind === SyntaxKind.Identifier &&
8658+
(<Identifier>element.name).text === typePredicateNode.parameterName.text) {
8659+
8660+
error(typePredicateNode.parameterName,
8661+
Diagnostics.Type_predicate_cannot_reference_element_0_in_a_binding_pattern,
8662+
typePredicate.parameterName);
8663+
hasReportedError = true;
8664+
break outer;
8665+
}
8666+
}
8667+
}
8668+
}
8669+
if (!hasReportedError) {
8670+
error(typePredicateNode.parameterName,
8671+
Diagnostics.Cannot_find_parameter_0,
8672+
typePredicate.parameterName);
8673+
}
86538674
}
86548675
}
86558676
else {
86568677
error(typePredicateNode,
8657-
Diagnostics.Type_predicates_are_only_allowed_in_return_type_position_for_arrow_functions_function_expressions_function_declarations_function_types_and_method_declarations);
8678+
Diagnostics.Type_predicates_are_only_allowed_in_return_type_position_for_functions_and_methods);
86588679
}
86598680
}
86608681
else {
@@ -11295,8 +11316,8 @@ module ts {
1129511316
}
1129611317

1129711318
function checkTypePredicate(node: TypePredicateNode) {
11298-
if(!isInATypePredicateCompatiblePosition(node)) {
11299-
error(node, Diagnostics.Type_predicates_are_only_allowed_in_return_type_position_for_arrow_functions_function_expressions_function_declarations_function_types_and_method_declarations);
11319+
if(!isInLegalTypePredicatePosition(node)) {
11320+
error(node, Diagnostics.Type_predicates_are_only_allowed_in_return_type_position_for_functions_and_methods);
1130011321
}
1130111322
}
1130211323

src/compiler/diagnosticInformationMap.generated.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,9 @@ module ts {
183183
Cannot_find_parameter_0: { code: 1225, category: DiagnosticCategory.Error, key: "Cannot find parameter '{0}'." },
184184
Type_predicate_0_is_not_assignable_to_1: { code: 1226, category: DiagnosticCategory.Error, key: "Type predicate '{0}' is not assignable to '{1}'." },
185185
Parameter_0_is_not_in_the_same_position_as_parameter_1: { code: 1227, category: DiagnosticCategory.Error, key: "Parameter '{0}' is not in the same position as parameter '{1}'." },
186-
Type_predicates_are_only_allowed_in_return_type_position_for_arrow_functions_function_expressions_function_declarations_function_types_and_method_declarations: { code: 1228, category: DiagnosticCategory.Error, key: "Type predicates are only allowed in return type position for arrow functions, function expressions, function declarations, function types and method declarations." },
187-
Type_predicate_cannot_reference_a_spread_parameter: { code: 1229, category: DiagnosticCategory.Error, key: "Type predicate cannot reference a spread parameter." },
186+
Type_predicates_are_only_allowed_in_return_type_position_for_functions_and_methods: { code: 1228, category: DiagnosticCategory.Error, key: "Type predicates are only allowed in return type position for functions and methods." },
187+
Type_predicate_cannot_reference_a_rest_parameter: { code: 1229, category: DiagnosticCategory.Error, key: "Type predicate cannot reference a rest parameter." },
188+
Type_predicate_cannot_reference_element_0_in_a_binding_pattern: { code: 1230, category: DiagnosticCategory.Error, key: "Type predicate cannot reference element '{0}' in a binding pattern." },
188189
Duplicate_identifier_0: { code: 2300, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." },
189190
Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor: { code: 2301, category: DiagnosticCategory.Error, key: "Initializer of instance member variable '{0}' cannot reference identifier '{1}' declared in the constructor." },
190191
Static_members_cannot_reference_class_type_parameters: { code: 2302, category: DiagnosticCategory.Error, key: "Static members cannot reference class type parameters." },

src/compiler/diagnosticMessages.json

+6-2
Original file line numberDiff line numberDiff line change
@@ -719,14 +719,18 @@
719719
"category": "Error",
720720
"code": 1227
721721
},
722-
"Type predicates are only allowed in return type position for arrow functions, function expressions, function declarations, function types and method declarations.": {
722+
"Type predicates are only allowed in return type position for functions and methods.": {
723723
"category": "Error",
724724
"code": 1228
725725
},
726-
"Type predicate cannot reference a spread parameter.": {
726+
"Type predicate cannot reference a rest parameter.": {
727727
"category": "Error",
728728
"code": 1229
729729
},
730+
"Type predicate cannot reference element '{0}' in a binding pattern.": {
731+
"category": "Error",
732+
"code": 1230
733+
},
730734

731735

732736
"Duplicate identifier '{0}'.": {

tests/baselines/reference/typeGuardFunction.js

+5
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ if(isA(union)) {
3838
union.propA;
3939
}
4040

41+
// Call signature
42+
interface I1 {
43+
(p1: A): p1 is C;
44+
}
45+
4146
// The parameter index and argument index for the type guard target is matching.
4247
// The type predicate type is assignable to the parameter type.
4348
declare function isC_multipleParams(p1, p2): p1 is C;

tests/baselines/reference/typeGuardFunction.symbols

+38-28
Original file line numberDiff line numberDiff line change
@@ -91,16 +91,26 @@ if(isA(union)) {
9191
>propA : Symbol(A.propA, Decl(typeGuardFunction.ts, 1, 9))
9292
}
9393

94+
// Call signature
95+
interface I1 {
96+
>I1 : Symbol(I1, Decl(typeGuardFunction.ts, 37, 1))
97+
98+
(p1: A): p1 is C;
99+
>p1 : Symbol(p1, Decl(typeGuardFunction.ts, 41, 5))
100+
>A : Symbol(A, Decl(typeGuardFunction.ts, 0, 0))
101+
>C : Symbol(C, Decl(typeGuardFunction.ts, 7, 1))
102+
}
103+
94104
// The parameter index and argument index for the type guard target is matching.
95105
// The type predicate type is assignable to the parameter type.
96106
declare function isC_multipleParams(p1, p2): p1 is C;
97-
>isC_multipleParams : Symbol(isC_multipleParams, Decl(typeGuardFunction.ts, 37, 1))
98-
>p1 : Symbol(p1, Decl(typeGuardFunction.ts, 41, 36))
99-
>p2 : Symbol(p2, Decl(typeGuardFunction.ts, 41, 39))
107+
>isC_multipleParams : Symbol(isC_multipleParams, Decl(typeGuardFunction.ts, 42, 1))
108+
>p1 : Symbol(p1, Decl(typeGuardFunction.ts, 46, 36))
109+
>p2 : Symbol(p2, Decl(typeGuardFunction.ts, 46, 39))
100110
>C : Symbol(C, Decl(typeGuardFunction.ts, 7, 1))
101111

102112
if (isC_multipleParams(a, 0)) {
103-
>isC_multipleParams : Symbol(isC_multipleParams, Decl(typeGuardFunction.ts, 37, 1))
113+
>isC_multipleParams : Symbol(isC_multipleParams, Decl(typeGuardFunction.ts, 42, 1))
104114
>a : Symbol(a, Decl(typeGuardFunction.ts, 19, 3))
105115

106116
a.propC;
@@ -111,20 +121,20 @@ if (isC_multipleParams(a, 0)) {
111121

112122
// Methods
113123
var obj: {
114-
>obj : Symbol(obj, Decl(typeGuardFunction.ts, 47, 3))
124+
>obj : Symbol(obj, Decl(typeGuardFunction.ts, 52, 3))
115125

116126
func1(p1: A): p1 is C;
117-
>func1 : Symbol(func1, Decl(typeGuardFunction.ts, 47, 10))
118-
>p1 : Symbol(p1, Decl(typeGuardFunction.ts, 48, 10))
127+
>func1 : Symbol(func1, Decl(typeGuardFunction.ts, 52, 10))
128+
>p1 : Symbol(p1, Decl(typeGuardFunction.ts, 53, 10))
119129
>A : Symbol(A, Decl(typeGuardFunction.ts, 0, 0))
120130
>C : Symbol(C, Decl(typeGuardFunction.ts, 7, 1))
121131
}
122132
class D {
123-
>D : Symbol(D, Decl(typeGuardFunction.ts, 49, 1))
133+
>D : Symbol(D, Decl(typeGuardFunction.ts, 54, 1))
124134

125135
method1(p1: A): p1 is C {
126-
>method1 : Symbol(method1, Decl(typeGuardFunction.ts, 50, 9))
127-
>p1 : Symbol(p1, Decl(typeGuardFunction.ts, 51, 12))
136+
>method1 : Symbol(method1, Decl(typeGuardFunction.ts, 55, 9))
137+
>p1 : Symbol(p1, Decl(typeGuardFunction.ts, 56, 12))
128138
>A : Symbol(A, Decl(typeGuardFunction.ts, 0, 0))
129139
>C : Symbol(C, Decl(typeGuardFunction.ts, 7, 1))
130140

@@ -134,23 +144,23 @@ class D {
134144

135145
// Arrow function
136146
let f1 = (p1: A): p1 is C => false;
137-
>f1 : Symbol(f1, Decl(typeGuardFunction.ts, 57, 3))
138-
>p1 : Symbol(p1, Decl(typeGuardFunction.ts, 57, 10))
147+
>f1 : Symbol(f1, Decl(typeGuardFunction.ts, 62, 3))
148+
>p1 : Symbol(p1, Decl(typeGuardFunction.ts, 62, 10))
139149
>A : Symbol(A, Decl(typeGuardFunction.ts, 0, 0))
140150
>C : Symbol(C, Decl(typeGuardFunction.ts, 7, 1))
141151

142152
// Function type
143153
declare function f2(p1: (p1: A) => p1 is C);
144-
>f2 : Symbol(f2, Decl(typeGuardFunction.ts, 57, 35))
145-
>p1 : Symbol(p1, Decl(typeGuardFunction.ts, 60, 20))
146-
>p1 : Symbol(p1, Decl(typeGuardFunction.ts, 60, 25))
154+
>f2 : Symbol(f2, Decl(typeGuardFunction.ts, 62, 35))
155+
>p1 : Symbol(p1, Decl(typeGuardFunction.ts, 65, 20))
156+
>p1 : Symbol(p1, Decl(typeGuardFunction.ts, 65, 25))
147157
>A : Symbol(A, Decl(typeGuardFunction.ts, 0, 0))
148158
>C : Symbol(C, Decl(typeGuardFunction.ts, 7, 1))
149159

150160
// Function expressions
151161
f2(function(p1: A): p1 is C {
152-
>f2 : Symbol(f2, Decl(typeGuardFunction.ts, 57, 35))
153-
>p1 : Symbol(p1, Decl(typeGuardFunction.ts, 63, 12))
162+
>f2 : Symbol(f2, Decl(typeGuardFunction.ts, 62, 35))
163+
>p1 : Symbol(p1, Decl(typeGuardFunction.ts, 68, 12))
154164
>A : Symbol(A, Decl(typeGuardFunction.ts, 0, 0))
155165
>C : Symbol(C, Decl(typeGuardFunction.ts, 7, 1))
156166

@@ -159,35 +169,35 @@ f2(function(p1: A): p1 is C {
159169

160170
// Evaluations are asssignable to boolean.
161171
declare function acceptingBoolean(a: boolean);
162-
>acceptingBoolean : Symbol(acceptingBoolean, Decl(typeGuardFunction.ts, 65, 3))
163-
>a : Symbol(a, Decl(typeGuardFunction.ts, 68, 34))
172+
>acceptingBoolean : Symbol(acceptingBoolean, Decl(typeGuardFunction.ts, 70, 3))
173+
>a : Symbol(a, Decl(typeGuardFunction.ts, 73, 34))
164174

165175
acceptingBoolean(isA(a));
166-
>acceptingBoolean : Symbol(acceptingBoolean, Decl(typeGuardFunction.ts, 65, 3))
176+
>acceptingBoolean : Symbol(acceptingBoolean, Decl(typeGuardFunction.ts, 70, 3))
167177
>isA : Symbol(isA, Decl(typeGuardFunction.ts, 11, 1))
168178
>a : Symbol(a, Decl(typeGuardFunction.ts, 19, 3))
169179

170180
// Type predicates with different parameter name.
171181
declare function acceptingTypeGuardFunction(p1: (item) => item is A);
172-
>acceptingTypeGuardFunction : Symbol(acceptingTypeGuardFunction, Decl(typeGuardFunction.ts, 69, 25))
173-
>p1 : Symbol(p1, Decl(typeGuardFunction.ts, 72, 44))
174-
>item : Symbol(item, Decl(typeGuardFunction.ts, 72, 49))
182+
>acceptingTypeGuardFunction : Symbol(acceptingTypeGuardFunction, Decl(typeGuardFunction.ts, 74, 25))
183+
>p1 : Symbol(p1, Decl(typeGuardFunction.ts, 77, 44))
184+
>item : Symbol(item, Decl(typeGuardFunction.ts, 77, 49))
175185
>A : Symbol(A, Decl(typeGuardFunction.ts, 0, 0))
176186

177187
acceptingTypeGuardFunction(isA);
178-
>acceptingTypeGuardFunction : Symbol(acceptingTypeGuardFunction, Decl(typeGuardFunction.ts, 69, 25))
188+
>acceptingTypeGuardFunction : Symbol(acceptingTypeGuardFunction, Decl(typeGuardFunction.ts, 74, 25))
179189
>isA : Symbol(isA, Decl(typeGuardFunction.ts, 11, 1))
180190

181191
// Binary expressions
182192
let union2: C | B;
183-
>union2 : Symbol(union2, Decl(typeGuardFunction.ts, 76, 3))
193+
>union2 : Symbol(union2, Decl(typeGuardFunction.ts, 81, 3))
184194
>C : Symbol(C, Decl(typeGuardFunction.ts, 7, 1))
185195
>B : Symbol(B, Decl(typeGuardFunction.ts, 3, 1))
186196

187197
let union3: boolean | B = isA(union2) || union2;
188-
>union3 : Symbol(union3, Decl(typeGuardFunction.ts, 77, 3))
198+
>union3 : Symbol(union3, Decl(typeGuardFunction.ts, 82, 3))
189199
>B : Symbol(B, Decl(typeGuardFunction.ts, 3, 1))
190200
>isA : Symbol(isA, Decl(typeGuardFunction.ts, 11, 1))
191-
>union2 : Symbol(union2, Decl(typeGuardFunction.ts, 76, 3))
192-
>union2 : Symbol(union2, Decl(typeGuardFunction.ts, 76, 3))
201+
>union2 : Symbol(union2, Decl(typeGuardFunction.ts, 81, 3))
202+
>union2 : Symbol(union2, Decl(typeGuardFunction.ts, 81, 3))
193203

tests/baselines/reference/typeGuardFunction.types

+11
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,17 @@ if(isA(union)) {
9797
>propA : number
9898
}
9999

100+
// Call signature
101+
interface I1 {
102+
>I1 : I1
103+
104+
(p1: A): p1 is C;
105+
>p1 : A
106+
>A : A
107+
>p1 : any
108+
>C : C
109+
}
110+
100111
// The parameter index and argument index for the type guard target is matching.
101112
// The type predicate type is assignable to the parameter type.
102113
declare function isC_multipleParams(p1, p2): p1 is C;

0 commit comments

Comments
 (0)