diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 72bfc80ac49..c7ccb98f8f2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5642,13 +5642,13 @@ module ts { } if (targetType) { - return getOptionalNarrowedType(type, targetType); + return getNarrowedType(type, targetType); } return type; } - function getOptionalNarrowedType(originalType: Type, narrowedTypeCandidate: Type) { + function getNarrowedType(originalType: Type, narrowedTypeCandidate: Type) { // Narrow to the target type if it's a subtype of the current type if (isTypeSubtypeOf(narrowedTypeCandidate, originalType)) { return narrowedTypeCandidate; @@ -5675,7 +5675,7 @@ module ts { } return type; } - return getOptionalNarrowedType(type, signature.typePredicate.type); + return getNarrowedType(type, signature.typePredicate.type); } return type; } @@ -8601,6 +8601,19 @@ module ts { } } + function isInATypePredicateCompatiblePosition(node: Node): boolean { + switch (node.parent.kind) { + case SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.FunctionType: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + return true; + } + return false; + } + function checkSignatureDeclaration(node: SignatureDeclaration) { // Grammar checking if (node.kind === SyntaxKind.IndexSignature) { @@ -8621,15 +8634,17 @@ module ts { if (node.type.kind === SyntaxKind.TypePredicate) { let typePredicate = getSignatureFromDeclaration(node).typePredicate; let typePredicateNode = node.type; - if (typePredicateNode.type.kind === SyntaxKind.TypePredicate) { - error(typePredicateNode.type, - Diagnostics.Type_predicates_are_only_allowed_in_return_type_position); - } - else { + if (isInATypePredicateCompatiblePosition(typePredicateNode)) { if (typePredicate.parameterIndex >= 0) { - checkTypeAssignableTo(typePredicate.type, - getTypeAtLocation(node.parameters[typePredicate.parameterIndex]), - typePredicateNode.type); + if (node.parameters[typePredicate.parameterIndex].dotDotDotToken) { + error(typePredicateNode.parameterName, + Diagnostics.Type_predicate_cannot_reference_a_spread_parameter); + } + else { + checkTypeAssignableTo(typePredicate.type, + getTypeAtLocation(node.parameters[typePredicate.parameterIndex]), + typePredicateNode.type); + } } else if (typePredicateNode.parameterName) { error(typePredicateNode.parameterName, @@ -8637,6 +8652,10 @@ module ts { typePredicate.parameterName); } } + else { + error(typePredicateNode, + Diagnostics.Type_predicates_are_only_allowed_in_return_type_position_for_arrow_functions_function_expressions_function_declarations_function_types_and_method_declarations); + } } else { checkSourceElement(node.type); @@ -11275,6 +11294,12 @@ module ts { } } + function checkTypePredicate(node: TypePredicateNode) { + if(!isInATypePredicateCompatiblePosition(node)) { + error(node, Diagnostics.Type_predicates_are_only_allowed_in_return_type_position_for_arrow_functions_function_expressions_function_declarations_function_types_and_method_declarations); + } + } + function checkSourceElement(node: Node): void { if (!node) return; switch (node.kind) { @@ -11303,12 +11328,7 @@ module ts { case SyntaxKind.TypeReference: return checkTypeReferenceNode(node); case SyntaxKind.TypePredicate: - // Issue an error every time we encounter a type predicate. They are only allowed - // in return type positions in signature declarations. checkSignatureDeclaration(..) - // already have a specific check for type predicates, so every time we encounter a type - // predicate in checkSourceElement it must be in a non return type position. - error(node, Diagnostics.Type_predicates_are_only_allowed_in_return_type_position); - return; + return checkTypePredicate(node); case SyntaxKind.TypeQuery: return checkTypeQuery(node); case SyntaxKind.TypeLiteral: diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index 1457b52ba70..25d3730cc07 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -183,7 +183,8 @@ module ts { Cannot_find_parameter_0: { code: 1225, category: DiagnosticCategory.Error, key: "Cannot find parameter '{0}'." }, Type_predicate_0_is_not_assignable_to_1: { code: 1226, category: DiagnosticCategory.Error, key: "Type predicate '{0}' is not assignable to '{1}'." }, 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}'." }, - Type_predicates_are_only_allowed_in_return_type_position: { code: 1228, category: DiagnosticCategory.Error, key: "Type predicates are only allowed in return type position." }, + 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." }, + Type_predicate_cannot_reference_a_spread_parameter: { code: 1229, category: DiagnosticCategory.Error, key: "Type predicate cannot reference a spread parameter." }, Duplicate_identifier_0: { code: 2300, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." }, 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." }, Static_members_cannot_reference_class_type_parameters: { code: 2302, category: DiagnosticCategory.Error, key: "Static members cannot reference class type parameters." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 3c323f1402b..4008a6af1b1 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -719,10 +719,14 @@ "category": "Error", "code": 1227 }, - "Type predicates are only allowed in return type position.": { + "Type predicates are only allowed in return type position for arrow functions, function expressions, function declarations, function types and method declarations.": { "category": "Error", "code": 1228 }, + "Type predicate cannot reference a spread parameter.": { + "category": "Error", + "code": 1229 + }, "Duplicate identifier '{0}'.": { diff --git a/tests/baselines/reference/typeGuardFunction.js b/tests/baselines/reference/typeGuardFunction.js index d6b64c09d4d..5c256160bba 100644 --- a/tests/baselines/reference/typeGuardFunction.js +++ b/tests/baselines/reference/typeGuardFunction.js @@ -21,18 +21,18 @@ declare function retC(): C; var a: A; var b: B; -// Basic. +// Basic if (isC(a)) { a.propC; } -// Sub type. +// Sub type var subType: C; if(isA(subType)) { subType.propC; } -// Union type. +// Union type var union: A | B; if(isA(union)) { union.propA; @@ -45,6 +45,27 @@ if (isC_multipleParams(a, 0)) { a.propC; } +// Methods +var obj: { + func1(p1: A): p1 is C; +} +class D { + method1(p1: A): p1 is C { + return true; + } +} + +// Arrow function +let f1 = (p1: A): p1 is C => false; + +// Function type +declare function f2(p1: (p1: A) => p1 is C); + +// Function expressions +f2(function(p1: A): p1 is C { + return true; +}); + // Evaluations are asssignable to boolean. declare function acceptingBoolean(a: boolean); acceptingBoolean(isA(a)); @@ -53,6 +74,7 @@ acceptingBoolean(isA(a)); declare function acceptingTypeGuardFunction(p1: (item) => item is A); acceptingTypeGuardFunction(isA); +// Binary expressions let union2: C | B; let union3: boolean | B = isA(union2) || union2; @@ -82,16 +104,16 @@ var C = (function (_super) { })(A); var a; var b; -// Basic. +// Basic if (isC(a)) { a.propC; } -// Sub type. +// Sub type var subType; if (isA(subType)) { subType.propC; } -// Union type. +// Union type var union; if (isA(union)) { union.propA; @@ -99,7 +121,24 @@ if (isA(union)) { if (isC_multipleParams(a, 0)) { a.propC; } +// Methods +var obj; +var D = (function () { + function D() { + } + D.prototype.method1 = function (p1) { + return true; + }; + return D; +})(); +// Arrow function +var f1 = function (p1) { return false; }; +// Function expressions +f2(function (p1) { + return true; +}); acceptingBoolean(isA(a)); acceptingTypeGuardFunction(isA); +// Binary expressions var union2; var union3 = isA(union2) || union2; diff --git a/tests/baselines/reference/typeGuardFunction.symbols b/tests/baselines/reference/typeGuardFunction.symbols index f9180d56b0b..5b5fe1ec855 100644 --- a/tests/baselines/reference/typeGuardFunction.symbols +++ b/tests/baselines/reference/typeGuardFunction.symbols @@ -49,7 +49,7 @@ var b: B; >b : Symbol(b, Decl(typeGuardFunction.ts, 20, 3)) >B : Symbol(B, Decl(typeGuardFunction.ts, 3, 1)) -// Basic. +// Basic if (isC(a)) { >isC : Symbol(isC, Decl(typeGuardFunction.ts, 14, 39)) >a : Symbol(a, Decl(typeGuardFunction.ts, 19, 3)) @@ -60,7 +60,7 @@ if (isC(a)) { >propC : Symbol(C.propC, Decl(typeGuardFunction.ts, 9, 19)) } -// Sub type. +// Sub type var subType: C; >subType : Symbol(subType, Decl(typeGuardFunction.ts, 28, 3)) >C : Symbol(C, Decl(typeGuardFunction.ts, 7, 1)) @@ -75,7 +75,7 @@ if(isA(subType)) { >propC : Symbol(C.propC, Decl(typeGuardFunction.ts, 9, 19)) } -// Union type. +// Union type var union: A | B; >union : Symbol(union, Decl(typeGuardFunction.ts, 34, 3)) >A : Symbol(A, Decl(typeGuardFunction.ts, 0, 0)) @@ -109,36 +109,85 @@ if (isC_multipleParams(a, 0)) { >propC : Symbol(C.propC, Decl(typeGuardFunction.ts, 9, 19)) } +// Methods +var obj: { +>obj : Symbol(obj, Decl(typeGuardFunction.ts, 47, 3)) + + func1(p1: A): p1 is C; +>func1 : Symbol(func1, Decl(typeGuardFunction.ts, 47, 10)) +>p1 : Symbol(p1, Decl(typeGuardFunction.ts, 48, 10)) +>A : Symbol(A, Decl(typeGuardFunction.ts, 0, 0)) +>C : Symbol(C, Decl(typeGuardFunction.ts, 7, 1)) +} +class D { +>D : Symbol(D, Decl(typeGuardFunction.ts, 49, 1)) + + method1(p1: A): p1 is C { +>method1 : Symbol(method1, Decl(typeGuardFunction.ts, 50, 9)) +>p1 : Symbol(p1, Decl(typeGuardFunction.ts, 51, 12)) +>A : Symbol(A, Decl(typeGuardFunction.ts, 0, 0)) +>C : Symbol(C, Decl(typeGuardFunction.ts, 7, 1)) + + return true; + } +} + +// Arrow function +let f1 = (p1: A): p1 is C => false; +>f1 : Symbol(f1, Decl(typeGuardFunction.ts, 57, 3)) +>p1 : Symbol(p1, Decl(typeGuardFunction.ts, 57, 10)) +>A : Symbol(A, Decl(typeGuardFunction.ts, 0, 0)) +>C : Symbol(C, Decl(typeGuardFunction.ts, 7, 1)) + +// Function type +declare function f2(p1: (p1: A) => p1 is C); +>f2 : Symbol(f2, Decl(typeGuardFunction.ts, 57, 35)) +>p1 : Symbol(p1, Decl(typeGuardFunction.ts, 60, 20)) +>p1 : Symbol(p1, Decl(typeGuardFunction.ts, 60, 25)) +>A : Symbol(A, Decl(typeGuardFunction.ts, 0, 0)) +>C : Symbol(C, Decl(typeGuardFunction.ts, 7, 1)) + +// Function expressions +f2(function(p1: A): p1 is C { +>f2 : Symbol(f2, Decl(typeGuardFunction.ts, 57, 35)) +>p1 : Symbol(p1, Decl(typeGuardFunction.ts, 63, 12)) +>A : Symbol(A, Decl(typeGuardFunction.ts, 0, 0)) +>C : Symbol(C, Decl(typeGuardFunction.ts, 7, 1)) + + return true; +}); + // Evaluations are asssignable to boolean. declare function acceptingBoolean(a: boolean); ->acceptingBoolean : Symbol(acceptingBoolean, Decl(typeGuardFunction.ts, 44, 1)) ->a : Symbol(a, Decl(typeGuardFunction.ts, 47, 34)) +>acceptingBoolean : Symbol(acceptingBoolean, Decl(typeGuardFunction.ts, 65, 3)) +>a : Symbol(a, Decl(typeGuardFunction.ts, 68, 34)) acceptingBoolean(isA(a)); ->acceptingBoolean : Symbol(acceptingBoolean, Decl(typeGuardFunction.ts, 44, 1)) +>acceptingBoolean : Symbol(acceptingBoolean, Decl(typeGuardFunction.ts, 65, 3)) >isA : Symbol(isA, Decl(typeGuardFunction.ts, 11, 1)) >a : Symbol(a, Decl(typeGuardFunction.ts, 19, 3)) // Type predicates with different parameter name. declare function acceptingTypeGuardFunction(p1: (item) => item is A); ->acceptingTypeGuardFunction : Symbol(acceptingTypeGuardFunction, Decl(typeGuardFunction.ts, 48, 25)) ->p1 : Symbol(p1, Decl(typeGuardFunction.ts, 51, 44)) ->item : Symbol(item, Decl(typeGuardFunction.ts, 51, 49)) +>acceptingTypeGuardFunction : Symbol(acceptingTypeGuardFunction, Decl(typeGuardFunction.ts, 69, 25)) +>p1 : Symbol(p1, Decl(typeGuardFunction.ts, 72, 44)) +>item : Symbol(item, Decl(typeGuardFunction.ts, 72, 49)) >A : Symbol(A, Decl(typeGuardFunction.ts, 0, 0)) acceptingTypeGuardFunction(isA); ->acceptingTypeGuardFunction : Symbol(acceptingTypeGuardFunction, Decl(typeGuardFunction.ts, 48, 25)) +>acceptingTypeGuardFunction : Symbol(acceptingTypeGuardFunction, Decl(typeGuardFunction.ts, 69, 25)) >isA : Symbol(isA, Decl(typeGuardFunction.ts, 11, 1)) +// Binary expressions let union2: C | B; ->union2 : Symbol(union2, Decl(typeGuardFunction.ts, 54, 3)) +>union2 : Symbol(union2, Decl(typeGuardFunction.ts, 76, 3)) >C : Symbol(C, Decl(typeGuardFunction.ts, 7, 1)) >B : Symbol(B, Decl(typeGuardFunction.ts, 3, 1)) let union3: boolean | B = isA(union2) || union2; ->union3 : Symbol(union3, Decl(typeGuardFunction.ts, 55, 3)) +>union3 : Symbol(union3, Decl(typeGuardFunction.ts, 77, 3)) >B : Symbol(B, Decl(typeGuardFunction.ts, 3, 1)) >isA : Symbol(isA, Decl(typeGuardFunction.ts, 11, 1)) ->union2 : Symbol(union2, Decl(typeGuardFunction.ts, 54, 3)) ->union2 : Symbol(union2, Decl(typeGuardFunction.ts, 54, 3)) +>union2 : Symbol(union2, Decl(typeGuardFunction.ts, 76, 3)) +>union2 : Symbol(union2, Decl(typeGuardFunction.ts, 76, 3)) diff --git a/tests/baselines/reference/typeGuardFunction.types b/tests/baselines/reference/typeGuardFunction.types index 2b3d1c40c8e..06e9be615e2 100644 --- a/tests/baselines/reference/typeGuardFunction.types +++ b/tests/baselines/reference/typeGuardFunction.types @@ -52,7 +52,7 @@ var b: B; >b : B >B : B -// Basic. +// Basic if (isC(a)) { >isC(a) : boolean >isC : (p1: any) => boolean @@ -64,7 +64,7 @@ if (isC(a)) { >propC : number } -// Sub type. +// Sub type var subType: C; >subType : C >C : C @@ -80,7 +80,7 @@ if(isA(subType)) { >propC : number } -// Union type. +// Union type var union: A | B; >union : A | B >A : A @@ -118,6 +118,66 @@ if (isC_multipleParams(a, 0)) { >propC : number } +// Methods +var obj: { +>obj : { func1(p1: A): boolean; } + + func1(p1: A): p1 is C; +>func1 : (p1: A) => boolean +>p1 : A +>A : A +>p1 : any +>C : C +} +class D { +>D : D + + method1(p1: A): p1 is C { +>method1 : (p1: A) => boolean +>p1 : A +>A : A +>p1 : any +>C : C + + return true; +>true : boolean + } +} + +// Arrow function +let f1 = (p1: A): p1 is C => false; +>f1 : (p1: A) => boolean +>(p1: A): p1 is C => false : (p1: A) => boolean +>p1 : A +>A : A +>p1 : any +>C : C +>false : boolean + +// Function type +declare function f2(p1: (p1: A) => p1 is C); +>f2 : (p1: (p1: A) => boolean) => any +>p1 : (p1: A) => boolean +>p1 : A +>A : A +>p1 : any +>C : C + +// Function expressions +f2(function(p1: A): p1 is C { +>f2(function(p1: A): p1 is C { return true;}) : any +>f2 : (p1: (p1: A) => boolean) => any +>function(p1: A): p1 is C { return true;} : (p1: A) => boolean +>p1 : A +>A : A +>p1 : any +>C : C + + return true; +>true : boolean + +}); + // Evaluations are asssignable to boolean. declare function acceptingBoolean(a: boolean); >acceptingBoolean : (a: boolean) => any @@ -143,6 +203,7 @@ acceptingTypeGuardFunction(isA); >acceptingTypeGuardFunction : (p1: (item: any) => boolean) => any >isA : (p1: any) => boolean +// Binary expressions let union2: C | B; >union2 : B | C >C : C diff --git a/tests/baselines/reference/typeGuardFunctionErrors.errors.txt b/tests/baselines/reference/typeGuardFunctionErrors.errors.txt index 0d5065395a9..bcef83601aa 100644 --- a/tests/baselines/reference/typeGuardFunctionErrors.errors.txt +++ b/tests/baselines/reference/typeGuardFunctionErrors.errors.txt @@ -1,5 +1,4 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(15,12): error TS2322: Type 'string' is not assignable to type 'boolean'. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(18,55): error TS1228: Type predicates are only allowed in return type position. tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(22,33): error TS2304: Cannot find name 'x'. tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(26,10): error TS2391: Function implementation is missing or not immediately following the declaration. tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(27,5): error TS1131: Property or signature expected. @@ -22,12 +21,18 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(81,1): Parameter 'p2' is not in the same position as parameter 'p1'. tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(87,1): error TS2322: Type '(p1: any, p2: any, p3: any) => boolean' is not assignable to type '(p1: any, p2: any) => boolean'. tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(92,56): error TS1225: Cannot find parameter 'p1'. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(95,9): error TS1228: Type predicates are only allowed in return type position. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(96,16): error TS1228: Type predicates are only allowed in return type position. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(97,20): error TS1228: Type predicates are only allowed in return type position. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(95,9): error TS1228: Type predicates are only allowed in return type position for arrow functions, function expressions, function declarations, function types and method declarations. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(96,16): error TS1228: Type predicates are only allowed in return type position for arrow functions, function expressions, function declarations, function types and method declarations. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(97,20): error TS1228: Type predicates are only allowed in return type position for arrow functions, function expressions, function declarations, function types and method declarations. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(103,25): error TS1228: Type predicates are only allowed in return type position for arrow functions, function expressions, function declarations, function types and method declarations. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(104,16): error TS2409: Return type of constructor signature must be assignable to the instance type of the class +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(106,20): error TS1228: Type predicates are only allowed in return type position for arrow functions, function expressions, function declarations, function types and method declarations. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(109,20): error TS1228: Type predicates are only allowed in return type position for arrow functions, function expressions, function declarations, function types and method declarations. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(110,16): error TS2408: Setters cannot return a value. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(115,20): error TS1229: Type predicate cannot reference a spread parameter. -==== tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts (21 errors) ==== +==== tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts (26 errors) ==== class A { propA: number; @@ -48,8 +53,6 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(97,20) } function hasTypeGuardTypeInsideTypeGuardType(x): x is x is A { - ~~~~~~ -!!! error TS1228: Type predicates are only allowed in return type position. return true; } @@ -166,12 +169,42 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(97,20) // Type predicates in non-return type positions var b1: b is A; ~~~~~~ -!!! error TS1228: Type predicates are only allowed in return type position. +!!! error TS1228: Type predicates are only allowed in return type position for arrow functions, function expressions, function declarations, function types and method declarations. function b2(a: b is A) {}; ~~~~~~ -!!! error TS1228: Type predicates are only allowed in return type position. +!!! error TS1228: Type predicates are only allowed in return type position for arrow functions, function expressions, function declarations, function types and method declarations. function b3(): A | b is A { ~~~~~~ -!!! error TS1228: Type predicates are only allowed in return type position. +!!! error TS1228: Type predicates are only allowed in return type position for arrow functions, function expressions, function declarations, function types and method declarations. return true; - }; \ No newline at end of file + }; + + // Non-compatiable type predicate positions for signature declarations + class D { + constructor(p1: A): p1 is C { + ~~~~~~~ +!!! error TS1228: Type predicates are only allowed in return type position for arrow functions, function expressions, function declarations, function types and method declarations. + return true; + ~~~~ +!!! error TS2409: Return type of constructor signature must be assignable to the instance type of the class + } + get m1(p1: A): p1 is C { + ~~~~~~~ +!!! error TS1228: Type predicates are only allowed in return type position for arrow functions, function expressions, function declarations, function types and method declarations. + return true; + } + set m2(p1: A): p1 is C { + ~~~~~~~ +!!! error TS1228: Type predicates are only allowed in return type position for arrow functions, function expressions, function declarations, function types and method declarations. + return true; + ~~~~ +!!! error TS2408: Setters cannot return a value. + } + } + + // Reference to spread parameter + function b4(...a): a is A { + ~ +!!! error TS1229: Type predicate cannot reference a spread parameter. + return true; + } \ No newline at end of file diff --git a/tests/baselines/reference/typeGuardFunctionErrors.js b/tests/baselines/reference/typeGuardFunctionErrors.js index 0617cc1495a..2d3ccc561ed 100644 --- a/tests/baselines/reference/typeGuardFunctionErrors.js +++ b/tests/baselines/reference/typeGuardFunctionErrors.js @@ -97,7 +97,25 @@ var b1: b is A; function b2(a: b is A) {}; function b3(): A | b is A { return true; -}; +}; + +// Non-compatiable type predicate positions for signature declarations +class D { + constructor(p1: A): p1 is C { + return true; + } + get m1(p1: A): p1 is C { + return true; + } + set m2(p1: A): p1 is C { + return true; + } +} + +// Reference to spread parameter +function b4(...a): a is A { + return true; +} //// [typeGuardFunctionErrors.js] var __extends = (this && this.__extends) || function (d, b) { @@ -183,3 +201,32 @@ function b3() { return true; } ; +// Non-compatiable type predicate positions for signature declarations +var D = (function () { + function D(p1) { + return true; + } + Object.defineProperty(D.prototype, "m1", { + get: function (p1) { + return true; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(D.prototype, "m2", { + set: function (p1) { + return true; + }, + enumerable: true, + configurable: true + }); + return D; +})(); +// Reference to spread parameter +function b4() { + var a = []; + for (var _i = 0; _i < arguments.length; _i++) { + a[_i - 0] = arguments[_i]; + } + return true; +} diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardFunction.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardFunction.ts index 93cfd90ceb5..316a1483380 100644 --- a/tests/cases/conformance/expressions/typeGuards/typeGuardFunction.ts +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardFunction.ts @@ -20,18 +20,18 @@ declare function retC(): C; var a: A; var b: B; -// Basic. +// Basic if (isC(a)) { a.propC; } -// Sub type. +// Sub type var subType: C; if(isA(subType)) { subType.propC; } -// Union type. +// Union type var union: A | B; if(isA(union)) { union.propA; @@ -44,6 +44,27 @@ if (isC_multipleParams(a, 0)) { a.propC; } +// Methods +var obj: { + func1(p1: A): p1 is C; +} +class D { + method1(p1: A): p1 is C { + return true; + } +} + +// Arrow function +let f1 = (p1: A): p1 is C => false; + +// Function type +declare function f2(p1: (p1: A) => p1 is C); + +// Function expressions +f2(function(p1: A): p1 is C { + return true; +}); + // Evaluations are asssignable to boolean. declare function acceptingBoolean(a: boolean); acceptingBoolean(isA(a)); @@ -52,5 +73,6 @@ acceptingBoolean(isA(a)); declare function acceptingTypeGuardFunction(p1: (item) => item is A); acceptingTypeGuardFunction(isA); +// Binary expressions let union2: C | B; let union3: boolean | B = isA(union2) || union2; \ No newline at end of file diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts index baae822ec2d..df1d0b974c4 100644 --- a/tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts @@ -96,4 +96,22 @@ var b1: b is A; function b2(a: b is A) {}; function b3(): A | b is A { return true; -}; \ No newline at end of file +}; + +// Non-compatiable type predicate positions for signature declarations +class D { + constructor(p1: A): p1 is C { + return true; + } + get m1(p1: A): p1 is C { + return true; + } + set m2(p1: A): p1 is C { + return true; + } +} + +// Reference to spread parameter +function b4(...a): a is A { + return true; +} \ No newline at end of file