Skip to content

Commit 487dff5

Browse files
committed
Fixes CR feedback
1 parent fa9a914 commit 487dff5

10 files changed

+352
-58
lines changed

src/compiler/checker.ts

+37-17
Original file line numberDiff line numberDiff line change
@@ -5642,13 +5642,13 @@ module ts {
56425642
}
56435643

56445644
if (targetType) {
5645-
return getOptionalNarrowedType(type, targetType);
5645+
return getNarrowedType(type, targetType);
56465646
}
56475647

56485648
return type;
56495649
}
56505650

5651-
function getOptionalNarrowedType(originalType: Type, narrowedTypeCandidate: Type) {
5651+
function getNarrowedType(originalType: Type, narrowedTypeCandidate: Type) {
56525652
// Narrow to the target type if it's a subtype of the current type
56535653
if (isTypeSubtypeOf(narrowedTypeCandidate, originalType)) {
56545654
return narrowedTypeCandidate;
@@ -5675,7 +5675,7 @@ module ts {
56755675
}
56765676
return type;
56775677
}
5678-
return getOptionalNarrowedType(type, signature.typePredicate.type);
5678+
return getNarrowedType(type, signature.typePredicate.type);
56795679
}
56805680
return type;
56815681
}
@@ -8601,6 +8601,19 @@ module ts {
86018601
}
86028602
}
86038603

8604+
function isInATypePredicateCompatiblePosition(node: Node): boolean {
8605+
switch (node.parent.kind) {
8606+
case SyntaxKind.ArrowFunction:
8607+
case SyntaxKind.FunctionDeclaration:
8608+
case SyntaxKind.FunctionExpression:
8609+
case SyntaxKind.FunctionType:
8610+
case SyntaxKind.MethodDeclaration:
8611+
case SyntaxKind.MethodSignature:
8612+
return true;
8613+
}
8614+
return false;
8615+
}
8616+
86048617
function checkSignatureDeclaration(node: SignatureDeclaration) {
86058618
// Grammar checking
86068619
if (node.kind === SyntaxKind.IndexSignature) {
@@ -8621,22 +8634,28 @@ module ts {
86218634
if (node.type.kind === SyntaxKind.TypePredicate) {
86228635
let typePredicate = getSignatureFromDeclaration(node).typePredicate;
86238636
let typePredicateNode = <TypePredicateNode>node.type;
8624-
if (typePredicateNode.type.kind === SyntaxKind.TypePredicate) {
8625-
error(typePredicateNode.type,
8626-
Diagnostics.Type_predicates_are_only_allowed_in_return_type_position);
8627-
}
8628-
else {
8637+
if (isInATypePredicateCompatiblePosition(typePredicateNode)) {
86298638
if (typePredicate.parameterIndex >= 0) {
8630-
checkTypeAssignableTo(typePredicate.type,
8631-
getTypeAtLocation(node.parameters[typePredicate.parameterIndex]),
8632-
typePredicateNode.type);
8639+
if (node.parameters[typePredicate.parameterIndex].dotDotDotToken) {
8640+
error(typePredicateNode.parameterName,
8641+
Diagnostics.Type_predicate_cannot_reference_a_spread_parameter);
8642+
}
8643+
else {
8644+
checkTypeAssignableTo(typePredicate.type,
8645+
getTypeAtLocation(node.parameters[typePredicate.parameterIndex]),
8646+
typePredicateNode.type);
8647+
}
86338648
}
86348649
else if (typePredicateNode.parameterName) {
86358650
error(typePredicateNode.parameterName,
86368651
Diagnostics.Cannot_find_parameter_0,
86378652
typePredicate.parameterName);
86388653
}
86398654
}
8655+
else {
8656+
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);
8658+
}
86408659
}
86418660
else {
86428661
checkSourceElement(node.type);
@@ -11275,6 +11294,12 @@ module ts {
1127511294
}
1127611295
}
1127711296

11297+
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);
11300+
}
11301+
}
11302+
1127811303
function checkSourceElement(node: Node): void {
1127911304
if (!node) return;
1128011305
switch (node.kind) {
@@ -11303,12 +11328,7 @@ module ts {
1130311328
case SyntaxKind.TypeReference:
1130411329
return checkTypeReferenceNode(<TypeReferenceNode>node);
1130511330
case SyntaxKind.TypePredicate:
11306-
// Issue an error every time we encounter a type predicate. They are only allowed
11307-
// in return type positions in signature declarations. checkSignatureDeclaration(..)
11308-
// already have a specific check for type predicates, so every time we encounter a type
11309-
// predicate in checkSourceElement it must be in a non return type position.
11310-
error(node, Diagnostics.Type_predicates_are_only_allowed_in_return_type_position);
11311-
return;
11331+
return checkTypePredicate(<TypePredicateNode>node);
1131211332
case SyntaxKind.TypeQuery:
1131311333
return checkTypeQuery(<TypeQueryNode>node);
1131411334
case SyntaxKind.TypeLiteral:

src/compiler/diagnosticInformationMap.generated.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,8 @@ 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: { code: 1228, category: DiagnosticCategory.Error, key: "Type predicates are only allowed in return type position." },
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." },
187188
Duplicate_identifier_0: { code: 2300, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." },
188189
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." },
189190
Static_members_cannot_reference_class_type_parameters: { code: 2302, category: DiagnosticCategory.Error, key: "Static members cannot reference class type parameters." },

src/compiler/diagnosticMessages.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -719,10 +719,14 @@
719719
"category": "Error",
720720
"code": 1227
721721
},
722-
"Type predicates are only allowed in return type position.": {
722+
"Type predicates are only allowed in return type position for arrow functions, function expressions, function declarations, function types and method declarations.": {
723723
"category": "Error",
724724
"code": 1228
725725
},
726+
"Type predicate cannot reference a spread parameter.": {
727+
"category": "Error",
728+
"code": 1229
729+
},
726730

727731

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

tests/baselines/reference/typeGuardFunction.js

+45-6
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,18 @@ declare function retC(): C;
2121
var a: A;
2222
var b: B;
2323

24-
// Basic.
24+
// Basic
2525
if (isC(a)) {
2626
a.propC;
2727
}
2828

29-
// Sub type.
29+
// Sub type
3030
var subType: C;
3131
if(isA(subType)) {
3232
subType.propC;
3333
}
3434

35-
// Union type.
35+
// Union type
3636
var union: A | B;
3737
if(isA(union)) {
3838
union.propA;
@@ -45,6 +45,27 @@ if (isC_multipleParams(a, 0)) {
4545
a.propC;
4646
}
4747

48+
// Methods
49+
var obj: {
50+
func1(p1: A): p1 is C;
51+
}
52+
class D {
53+
method1(p1: A): p1 is C {
54+
return true;
55+
}
56+
}
57+
58+
// Arrow function
59+
let f1 = (p1: A): p1 is C => false;
60+
61+
// Function type
62+
declare function f2(p1: (p1: A) => p1 is C);
63+
64+
// Function expressions
65+
f2(function(p1: A): p1 is C {
66+
return true;
67+
});
68+
4869
// Evaluations are asssignable to boolean.
4970
declare function acceptingBoolean(a: boolean);
5071
acceptingBoolean(isA(a));
@@ -53,6 +74,7 @@ acceptingBoolean(isA(a));
5374
declare function acceptingTypeGuardFunction(p1: (item) => item is A);
5475
acceptingTypeGuardFunction(isA);
5576

77+
// Binary expressions
5678
let union2: C | B;
5779
let union3: boolean | B = isA(union2) || union2;
5880

@@ -82,24 +104,41 @@ var C = (function (_super) {
82104
})(A);
83105
var a;
84106
var b;
85-
// Basic.
107+
// Basic
86108
if (isC(a)) {
87109
a.propC;
88110
}
89-
// Sub type.
111+
// Sub type
90112
var subType;
91113
if (isA(subType)) {
92114
subType.propC;
93115
}
94-
// Union type.
116+
// Union type
95117
var union;
96118
if (isA(union)) {
97119
union.propA;
98120
}
99121
if (isC_multipleParams(a, 0)) {
100122
a.propC;
101123
}
124+
// Methods
125+
var obj;
126+
var D = (function () {
127+
function D() {
128+
}
129+
D.prototype.method1 = function (p1) {
130+
return true;
131+
};
132+
return D;
133+
})();
134+
// Arrow function
135+
var f1 = function (p1) { return false; };
136+
// Function expressions
137+
f2(function (p1) {
138+
return true;
139+
});
102140
acceptingBoolean(isA(a));
103141
acceptingTypeGuardFunction(isA);
142+
// Binary expressions
104143
var union2;
105144
var union3 = isA(union2) || union2;

tests/baselines/reference/typeGuardFunction.symbols

+63-14
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ var b: B;
4949
>b : Symbol(b, Decl(typeGuardFunction.ts, 20, 3))
5050
>B : Symbol(B, Decl(typeGuardFunction.ts, 3, 1))
5151

52-
// Basic.
52+
// Basic
5353
if (isC(a)) {
5454
>isC : Symbol(isC, Decl(typeGuardFunction.ts, 14, 39))
5555
>a : Symbol(a, Decl(typeGuardFunction.ts, 19, 3))
@@ -60,7 +60,7 @@ if (isC(a)) {
6060
>propC : Symbol(C.propC, Decl(typeGuardFunction.ts, 9, 19))
6161
}
6262

63-
// Sub type.
63+
// Sub type
6464
var subType: C;
6565
>subType : Symbol(subType, Decl(typeGuardFunction.ts, 28, 3))
6666
>C : Symbol(C, Decl(typeGuardFunction.ts, 7, 1))
@@ -75,7 +75,7 @@ if(isA(subType)) {
7575
>propC : Symbol(C.propC, Decl(typeGuardFunction.ts, 9, 19))
7676
}
7777

78-
// Union type.
78+
// Union type
7979
var union: A | B;
8080
>union : Symbol(union, Decl(typeGuardFunction.ts, 34, 3))
8181
>A : Symbol(A, Decl(typeGuardFunction.ts, 0, 0))
@@ -109,36 +109,85 @@ if (isC_multipleParams(a, 0)) {
109109
>propC : Symbol(C.propC, Decl(typeGuardFunction.ts, 9, 19))
110110
}
111111

112+
// Methods
113+
var obj: {
114+
>obj : Symbol(obj, Decl(typeGuardFunction.ts, 47, 3))
115+
116+
func1(p1: A): p1 is C;
117+
>func1 : Symbol(func1, Decl(typeGuardFunction.ts, 47, 10))
118+
>p1 : Symbol(p1, Decl(typeGuardFunction.ts, 48, 10))
119+
>A : Symbol(A, Decl(typeGuardFunction.ts, 0, 0))
120+
>C : Symbol(C, Decl(typeGuardFunction.ts, 7, 1))
121+
}
122+
class D {
123+
>D : Symbol(D, Decl(typeGuardFunction.ts, 49, 1))
124+
125+
method1(p1: A): p1 is C {
126+
>method1 : Symbol(method1, Decl(typeGuardFunction.ts, 50, 9))
127+
>p1 : Symbol(p1, Decl(typeGuardFunction.ts, 51, 12))
128+
>A : Symbol(A, Decl(typeGuardFunction.ts, 0, 0))
129+
>C : Symbol(C, Decl(typeGuardFunction.ts, 7, 1))
130+
131+
return true;
132+
}
133+
}
134+
135+
// Arrow function
136+
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))
139+
>A : Symbol(A, Decl(typeGuardFunction.ts, 0, 0))
140+
>C : Symbol(C, Decl(typeGuardFunction.ts, 7, 1))
141+
142+
// Function type
143+
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))
147+
>A : Symbol(A, Decl(typeGuardFunction.ts, 0, 0))
148+
>C : Symbol(C, Decl(typeGuardFunction.ts, 7, 1))
149+
150+
// Function expressions
151+
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))
154+
>A : Symbol(A, Decl(typeGuardFunction.ts, 0, 0))
155+
>C : Symbol(C, Decl(typeGuardFunction.ts, 7, 1))
156+
157+
return true;
158+
});
159+
112160
// Evaluations are asssignable to boolean.
113161
declare function acceptingBoolean(a: boolean);
114-
>acceptingBoolean : Symbol(acceptingBoolean, Decl(typeGuardFunction.ts, 44, 1))
115-
>a : Symbol(a, Decl(typeGuardFunction.ts, 47, 34))
162+
>acceptingBoolean : Symbol(acceptingBoolean, Decl(typeGuardFunction.ts, 65, 3))
163+
>a : Symbol(a, Decl(typeGuardFunction.ts, 68, 34))
116164

117165
acceptingBoolean(isA(a));
118-
>acceptingBoolean : Symbol(acceptingBoolean, Decl(typeGuardFunction.ts, 44, 1))
166+
>acceptingBoolean : Symbol(acceptingBoolean, Decl(typeGuardFunction.ts, 65, 3))
119167
>isA : Symbol(isA, Decl(typeGuardFunction.ts, 11, 1))
120168
>a : Symbol(a, Decl(typeGuardFunction.ts, 19, 3))
121169

122170
// Type predicates with different parameter name.
123171
declare function acceptingTypeGuardFunction(p1: (item) => item is A);
124-
>acceptingTypeGuardFunction : Symbol(acceptingTypeGuardFunction, Decl(typeGuardFunction.ts, 48, 25))
125-
>p1 : Symbol(p1, Decl(typeGuardFunction.ts, 51, 44))
126-
>item : Symbol(item, Decl(typeGuardFunction.ts, 51, 49))
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))
127175
>A : Symbol(A, Decl(typeGuardFunction.ts, 0, 0))
128176

129177
acceptingTypeGuardFunction(isA);
130-
>acceptingTypeGuardFunction : Symbol(acceptingTypeGuardFunction, Decl(typeGuardFunction.ts, 48, 25))
178+
>acceptingTypeGuardFunction : Symbol(acceptingTypeGuardFunction, Decl(typeGuardFunction.ts, 69, 25))
131179
>isA : Symbol(isA, Decl(typeGuardFunction.ts, 11, 1))
132180

181+
// Binary expressions
133182
let union2: C | B;
134-
>union2 : Symbol(union2, Decl(typeGuardFunction.ts, 54, 3))
183+
>union2 : Symbol(union2, Decl(typeGuardFunction.ts, 76, 3))
135184
>C : Symbol(C, Decl(typeGuardFunction.ts, 7, 1))
136185
>B : Symbol(B, Decl(typeGuardFunction.ts, 3, 1))
137186

138187
let union3: boolean | B = isA(union2) || union2;
139-
>union3 : Symbol(union3, Decl(typeGuardFunction.ts, 55, 3))
188+
>union3 : Symbol(union3, Decl(typeGuardFunction.ts, 77, 3))
140189
>B : Symbol(B, Decl(typeGuardFunction.ts, 3, 1))
141190
>isA : Symbol(isA, Decl(typeGuardFunction.ts, 11, 1))
142-
>union2 : Symbol(union2, Decl(typeGuardFunction.ts, 54, 3))
143-
>union2 : Symbol(union2, Decl(typeGuardFunction.ts, 54, 3))
191+
>union2 : Symbol(union2, Decl(typeGuardFunction.ts, 76, 3))
192+
>union2 : Symbol(union2, Decl(typeGuardFunction.ts, 76, 3))
144193

0 commit comments

Comments
 (0)