Adds PR feedback and removed references to typeguard (class) methods

This commit is contained in:
Tingan Ho 2015-06-04 19:23:07 +08:00
parent 3aa0839d1b
commit 19e725636e
10 changed files with 96 additions and 386 deletions

View file

@ -1358,14 +1358,23 @@ module ts {
return result;
}
function typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string {
function getWriteResult<T>(data: T, enclosingDeclaration: Node, flags: TypeFormatFlags, method: (data: T, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags) => void) {
let writer = getSingleLineStringWriter();
getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
method(data, writer, enclosingDeclaration, flags);
let result = writer.string();
releaseStringWriter(writer);
return result;
}
function signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string {
let result = getWriteResult(signature, enclosingDeclaration, flags, getSymbolDisplayBuilder().buildSignatureDisplay);
return result;
}
function typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string {
let result = getWriteResult(type, enclosingDeclaration, flags, getSymbolDisplayBuilder().buildTypeDisplay);
let maxLength = compilerOptions.noErrorTruncation || flags & TypeFormatFlags.NoTruncation ? undefined : 100;
if (maxLength && result.length >= maxLength) {
result = result.substr(0, maxLength - "...".length) + "...";
@ -3234,20 +3243,13 @@ module ts {
if (classType) {
returnType = classType;
}
else if (declaration.typePredicate) {
else if (declaration.type && declaration.type.kind === SyntaxKind.TypePredicate) {
returnType = booleanType;
let typePredicateNode = declaration.typePredicate;
let links = getNodeLinks(typePredicateNode);
if (links.typePredicateParameterIndex === undefined) {
links.typePredicateParameterIndex = getTypePredicateParameterIndex(declaration.parameters, typePredicateNode.parameterName);
}
if (!links.typeFromTypePredicate) {
links.typeFromTypePredicate = getTypeFromTypeNode(declaration.typePredicate.type);
}
let typePredicateNode = <TypePredicateNode>declaration.type;
typePredicate = {
parameterName: typePredicateNode.parameterName ? typePredicateNode.parameterName.text : undefined,
parameterIndex: typePredicateNode.parameterName ? links.typePredicateParameterIndex : undefined,
type: links.typeFromTypePredicate
parameterIndex: typePredicateNode.parameterName ? getTypePredicateParameterIndex(declaration.parameters, typePredicateNode.parameterName) : undefined,
type: getTypeFromTypeNode(typePredicateNode.type)
};
}
else if (declaration.type) {
@ -4662,8 +4664,8 @@ module ts {
if (source.typePredicate && target.typePredicate) {
let hasDifferentParamaterIndex = source.typePredicate.parameterIndex !== target.typePredicate.parameterIndex;
let hasDifferentTypes = !isTypeIdenticalTo(source.typePredicate.type, target.typePredicate.type);
if (hasDifferentParamaterIndex || hasDifferentTypes) {
let hasDifferentTypes: boolean;
if (hasDifferentParamaterIndex || (hasDifferentTypes = !isTypeIdenticalTo(source.typePredicate.type, target.typePredicate.type))) {
if (reportErrors) {
let sourceParamText = source.typePredicate.parameterName;
let targetParamText = target.typePredicate.parameterName;
@ -4675,7 +4677,7 @@ module ts {
sourceParamText,
targetParamText);
}
if (hasDifferentTypes) {
else if (hasDifferentTypes) {
reportError(Diagnostics.Type_0_is_not_assignable_to_type_1,
sourceTypeText,
targetTypeText);
@ -4687,11 +4689,10 @@ module ts {
}
return Ternary.False;
}
return Ternary.True;
}
else if (!source.typePredicate && target.typePredicate) {
if (reportErrors) {
reportError(Diagnostics.A_non_type_guard_function_is_not_assignable_to_a_type_guard_function);
reportError(Diagnostics.Signature_0_must_have_a_type_predicate, signatureToString(source));
}
return Ternary.False;
}
@ -5231,12 +5232,12 @@ module ts {
if (source.typePredicate && target.typePredicate) {
if (target.typePredicate.parameterIndex === source.typePredicate.parameterIndex) {
// Return types from type predicates are treated as booleans. In order to infer types
// from type predicates we would need infer from the type from type predicates. Since
// we can't infer any type information from the return types. We can just add a return
// statement after the below infer statement.
// from type predicates we would need to infer from the type of type predicates. Since
// we can't infer any type information from the return types — we can just add a return
// statement after the below infer type statement.
inferFromTypes(source.typePredicate.type, target.typePredicate.type);
return;
}
return;
}
inferFromTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target));
}
@ -8635,37 +8636,28 @@ module ts {
forEach(node.parameters, checkParameter);
if (node.type) {
checkSourceElement(node.type);
}
if (node.typePredicate) {
let links = getNodeLinks(node.typePredicate);
if (links.typePredicateParameterIndex === undefined) {
links.typePredicateParameterIndex = getTypePredicateParameterIndex(node.parameters, node.typePredicate.parameterName);
}
if (!links.typeFromTypePredicate) {
links.typeFromTypePredicate = getTypeFromTypeNode(node.typePredicate.type);
}
if (links.typePredicateParameterIndex >= 0) {
checkTypeAssignableTo(links.typeFromTypePredicate,
getTypeAtLocation(node.parameters[links.typePredicateParameterIndex]),
node.typePredicate.type);
}
else if (node.typePredicate.parameterName) {
error(node.typePredicate.parameterName,
Diagnostics.Cannot_find_parameter_0,
node.typePredicate.parameterName.text);
if (node.type.kind === SyntaxKind.TypePredicate) {
let typePredicate = getSignatureFromDeclaration(node).typePredicate;
if ((<TypePredicateNode>node.type).type.kind === SyntaxKind.TypePredicate) {
error((<TypePredicateNode>node.type).type,
Diagnostics.Cannot_define_type_predicate_0_as_a_type_to_a_type_predicate,
getTextOfNode((<TypePredicateNode>node.type).type));
}
else {
if (typePredicate.parameterIndex >= 0) {
checkTypeAssignableTo(typePredicate.type,
getTypeAtLocation(node.parameters[typePredicate.parameterIndex]),
(<TypePredicateNode>node.type).type);
}
else if ((<TypePredicateNode>node.type).parameterName) {
error((<TypePredicateNode>node.type).parameterName,
Diagnostics.Cannot_find_parameter_0,
typePredicate.parameterName);
}
}
}
else {
let typeOfClass = getTypeAtLocation(node.parent);
if (!isTypeSubtypeOf(links.typeFromTypePredicate, typeOfClass) &&
!isTypeSubtypeOf(typeOfClass, links.typeFromTypePredicate)) {
error(node.typePredicate,
Diagnostics.Type_0_and_type_1_are_disjoint_types,
typeToString(links.typeFromTypePredicate),
typeToString(typeOfClass));
}
checkSourceElement(node.type);
}
}
@ -11300,6 +11292,10 @@ module ts {
links.exportsChecked = true;
}
}
function checkTypePredicateNode(node: TypePredicateNode) {
}
function checkSourceElement(node: Node): void {
if (!node) return;
@ -11328,6 +11324,8 @@ module ts {
return checkAccessorDeclaration(<AccessorDeclaration>node);
case SyntaxKind.TypeReference:
return checkTypeReferenceNode(<TypeReferenceNode>node);
case SyntaxKind.TypePredicate:
return checkTypePredicateNode(<TypePredicateNode>node);
case SyntaxKind.TypeQuery:
return checkTypeQuery(<TypeQueryNode>node);
case SyntaxKind.TypeLiteral:

View file

@ -179,12 +179,11 @@ module ts {
Generators_are_not_allowed_in_an_ambient_context: { code: 1221, category: DiagnosticCategory.Error, key: "Generators are not allowed in an ambient context." },
An_overload_signature_cannot_be_declared_as_a_generator: { code: 1222, category: DiagnosticCategory.Error, key: "An overload signature cannot be declared as a generator." },
_0_tag_already_specified: { code: 1223, category: DiagnosticCategory.Error, key: "'{0}' tag already specified." },
A_non_type_guard_function_is_not_assignable_to_a_type_guard_function: { code: 1224, category: DiagnosticCategory.Error, key: "A non-type guard function is not assignable to a type guard function." },
A_type_guard_function_can_only_return_a_boolean: { code: 1225, category: DiagnosticCategory.Error, key: "A type-guard function can only return a boolean." },
Cannot_find_parameter_0: { code: 1226, category: DiagnosticCategory.Error, key: "Cannot find parameter '{0}'." },
Type_predicate_0_is_not_assignable_to_1: { code: 1227, category: DiagnosticCategory.Error, key: "Type predicate '{0}' is not assignable to '{1}'." },
Parameter_0_is_not_in_the_same_position_as_parameter_1: { code: 1228, category: DiagnosticCategory.Error, key: "Parameter '{0}' is not in the same position as parameter '{1}'." },
Type_0_and_type_1_are_disjoint_types: { code: 1229, category: DiagnosticCategory.Error, key: "Type '{0}' and type '{1}' are disjoint types." },
Signature_0_must_have_a_type_predicate: { code: 1224, category: DiagnosticCategory.Error, key: "Signature '{0}' must have a type predicate." },
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}'." },
Cannot_define_type_predicate_0_as_a_type_to_a_type_predicate: { code: 1228, category: DiagnosticCategory.Error, key: "Cannot define type predicate '{0}' as a type to a type predicate." },
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." },

View file

@ -703,30 +703,26 @@
"category": "Error",
"code": 1223
},
"A non-type guard function is not assignable to a type guard function.": {
"Signature '{0}' must have a type predicate.": {
"category": "Error",
"code": 1224
},
"A type-guard function can only return a boolean.": {
"Cannot find parameter '{0}'.": {
"category": "Error",
"code": 1225
},
"Cannot find parameter '{0}'.": {
"Type predicate '{0}' is not assignable to '{1}'.": {
"category": "Error",
"code": 1226
},
"Type predicate '{0}' is not assignable to '{1}'.": {
"Parameter '{0}' is not in the same position as parameter '{1}'.": {
"category": "Error",
"code": 1227
},
"Parameter '{0}' is not in the same position as parameter '{1}'.": {
"Cannot define type predicate '{0}' as a type to a type predicate.": {
"category": "Error",
"code": 1228
},
"Type '{0}' and type '{1}' are disjoint types.": {
"category": "Error",
"code": 1229
},
"Duplicate identifier '{0}'.": {

View file

@ -81,8 +81,7 @@ module ts {
visitNodes(cbNodes, node.modifiers) ||
visitNodes(cbNodes, (<SignatureDeclaration>node).typeParameters) ||
visitNodes(cbNodes, (<SignatureDeclaration>node).parameters) ||
visitNode(cbNode, (<SignatureDeclaration>node).type) ||
visitNode(cbNode, (<SignatureDeclaration>node).typePredicate);
visitNode(cbNode, (<SignatureDeclaration>node).type);
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
case SyntaxKind.Constructor:
@ -99,7 +98,6 @@ module ts {
visitNodes(cbNodes, (<FunctionLikeDeclaration>node).typeParameters) ||
visitNodes(cbNodes, (<FunctionLikeDeclaration>node).parameters) ||
visitNode(cbNode, (<FunctionLikeDeclaration>node).type) ||
visitNode(cbNode, (<FunctionLikeDeclaration>node).typePredicate) ||
visitNode(cbNode, (<ArrowFunction>node).equalsGreaterThanToken) ||
visitNode(cbNode, (<FunctionLikeDeclaration>node).body);
case SyntaxKind.TypeReference:
@ -768,7 +766,7 @@ module ts {
return (contextFlags & ParserContextFlags.Decorator) !== 0;
}
function parseErrorAtCurrentToken(message: DiagnosticMessage, arg0?: any) {
function parseErrorAtCurrentToken(message: DiagnosticMessage, arg0?: any): void {
let start = scanner.getTokenPos();
let length = scanner.getTextPos() - start;
@ -2053,13 +2051,10 @@ module ts {
if (returnTokenRequired) {
parseExpected(returnToken);
parseTypePredicateOrReturnType(signature);
signature.type = parseType();
}
else if (parseOptional(returnToken)) {
parseTypePredicateOrReturnType(signature);
}
if (token === SyntaxKind.IsKeyword) {
parseTypePredicate(signature);
signature.type = parseType();
}
}
@ -2497,6 +2492,22 @@ module ts {
return result;
}
function parseTypePredicateOrHigher(): TypeNode {
let type = parseUnionTypeOrHigher();
if (token === SyntaxKind.IsKeyword &&
type.kind === SyntaxKind.TypeReference &&
(<TypeReferenceNode>type).typeName.kind === SyntaxKind.Identifier) {
nextToken();
let typePredicate = <TypePredicateNode>createNode(SyntaxKind.TypePredicate, type.pos);
typePredicate.parameterName = <Identifier>(<TypeReferenceNode>type).typeName;
typePredicate.type = parseType();
return finishNode(typePredicate);
}
return type;
}
function parseTypeWorker(): TypeNode {
if (isStartOfFunctionType()) {
@ -2505,7 +2516,7 @@ module ts {
if (token === SyntaxKind.NewKeyword) {
return parseFunctionOrConstructorType(SyntaxKind.ConstructorType);
}
return parseUnionTypeOrHigher();
return parseTypePredicateOrHigher();
}
function parseTypeAnnotation(): TypeNode {

View file

@ -608,9 +608,9 @@ module ts {
typeName: EntityName;
typeArguments?: NodeArray<TypeNode>;
}
export interface TypePredicateNode extends TypeNode {
parameterName?: Identifier;
parameterName: Identifier;
type: TypeNode;
}
@ -1387,7 +1387,7 @@ module ts {
export interface TypePredicate {
parameterName: string;
parameterIndex?: number;
parameterIndex: number;
type: Type;
}
@ -1577,8 +1577,6 @@ module ts {
assignmentChecks?: Map<boolean>; // Cache of assignment checks
hasReportedStatementInAmbientContext?: boolean; // Cache boolean if we report statements in ambient context
importOnRightSide?: Symbol; // for import declarations - import that appear on the right side
typePredicateParameterIndex?: number; // Index of type predicate parameter
typeFromTypePredicate?: Type; // Type from TypePredicate
}
export const enum TypeFlags {

View file

@ -1,14 +1,10 @@
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 TS2304: Cannot find name 'x'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(18,57): error TS1144: '{' or ';' expected.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(18,57): error TS2304: Cannot find name 'is'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(18,60): error TS1005: ';' expected.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(18,62): error TS1005: ';' expected.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(18,55): error TS1228: Cannot define type predicate 'x is A' as a type to a type predicate.
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.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(28,1): error TS1128: Declaration or statement expected.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(30,38): error TS1226: Cannot find parameter 'x'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(30,38): error TS1225: Cannot find parameter 'x'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(34,51): error TS2322: Type 'B' is not assignable to type 'A'.
Property 'propA' is missing in type 'B'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(38,56): error TS2322: Type 'number' is not assignable to type 'string'.
@ -20,15 +16,15 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(71,46)
Type predicate 'p1 is C' is not assignable to 'p1 is B'.
Type 'C' is not assignable to type 'B'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(75,1): error TS2322: Type '(p1: any, p2: any) => boolean' is not assignable to type '(p1: any, p2: any) => boolean'.
A non-type guard function is not assignable to a type guard function.
Signature '(p1: any, p2: any): boolean' must have a type predicate.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(81,1): error TS2322: Type '(p1: any, p2: any) => boolean' is not assignable to type '(p1: any, p2: any) => boolean'.
Type predicate 'p2 is A' is not assignable to 'p1 is A'.
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 TS1226: Cannot find parameter 'p1'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(92,56): error TS1225: Cannot find parameter 'p1'.
==== tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts (22 errors) ====
==== tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts (18 errors) ====
class A {
propA: number;
@ -49,16 +45,8 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(92,56)
}
function hasTypeGuardTypeInsideTypeGuardType(x): x is x is A {
~
!!! error TS2304: Cannot find name 'x'.
~~
!!! error TS1144: '{' or ';' expected.
~~
!!! error TS2304: Cannot find name 'is'.
~
!!! error TS1005: ';' expected.
~
!!! error TS1005: ';' expected.
~~~~~~
!!! error TS1228: Cannot define type predicate 'x is A' as a type to a type predicate.
return true;
}
@ -80,7 +68,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(92,56)
function hasNonMatchingParameter(y): x is A {
~
!!! error TS1226: Cannot find parameter 'x'.
!!! error TS1225: Cannot find parameter 'x'.
return true;
}
@ -145,7 +133,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(92,56)
assign1 = function(p1, p2): boolean {
~~~~~~~
!!! error TS2322: Type '(p1: any, p2: any) => boolean' is not assignable to type '(p1: any, p2: any) => boolean'.
!!! error TS2322: A non-type guard function is not assignable to a type guard function.
!!! error TS2322: Signature '(p1: any, p2: any): boolean' must have a type predicate.
return true;
};
@ -170,5 +158,5 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(92,56)
// Type guard paramater referring to a binding pattern
declare function destructureParameter({ p1, p2, p3 }): p1 is A;
~~
!!! error TS1226: Cannot find parameter 'p1'.
!!! error TS1225: Cannot find parameter 'p1'.

View file

@ -120,9 +120,7 @@ var C = (function (_super) {
function hasANonBooleanReturnStatement(x) {
return '';
}
is;
A;
{
function hasTypeGuardTypeInsideTypeGuardType(x) {
return true;
}
function hasMissingIsKeyword() {

View file

@ -1,73 +0,0 @@
tests/cases/conformance/expressions/typeGuards/typeGuardMethods.ts(14,12): error TS1229: Type 'A' and type 'B' are disjoint types.
tests/cases/conformance/expressions/typeGuards/typeGuardMethods.ts(17,12): error TS1229: Type 'C' and type 'B' are disjoint types.
==== tests/cases/conformance/expressions/typeGuards/typeGuardMethods.ts (2 errors) ====
class A {
propA: number;
isA(): this is A {
return true;
}
isC(): this is C {
return false;
}
}
class B {
propB: number;
isA(): this is A {
~~~~~~~~~
!!! error TS1229: Type 'A' and type 'B' are disjoint types.
return false;
}
isC(): this is C {
~~~~~~~~~
!!! error TS1229: Type 'C' and type 'B' are disjoint types.
return false;
}
}
class C extends A {
propC: number;
isA(): this is A {
return false;
}
isC(): this is C {
return true;
}
}
class D extends C {
isA(): this is A {
return false;
}
isString(x: any): x is string { // with parameter declaration
return true;
}
}
var a: A;
// Basic.
if (a.isC()) {
a.propC;
}
// Sub type.
var subType: C;
if(subType.isA()) {
subType.propC;
}
// Union type.
var union: A | B;
if(union.isA()) {
union.propA;
}
var b: any;
var d = new D;
if(d.isString(b)) {
b.length;
}

View file

@ -1,141 +0,0 @@
//// [typeGuardMethods.ts]
class A {
propA: number;
isA(): this is A {
return true;
}
isC(): this is C {
return false;
}
}
class B {
propB: number;
isA(): this is A {
return false;
}
isC(): this is C {
return false;
}
}
class C extends A {
propC: number;
isA(): this is A {
return false;
}
isC(): this is C {
return true;
}
}
class D extends C {
isA(): this is A {
return false;
}
isString(x: any): x is string { // with parameter declaration
return true;
}
}
var a: A;
// Basic.
if (a.isC()) {
a.propC;
}
// Sub type.
var subType: C;
if(subType.isA()) {
subType.propC;
}
// Union type.
var union: A | B;
if(union.isA()) {
union.propA;
}
var b: any;
var d = new D;
if(d.isString(b)) {
b.length;
}
//// [typeGuardMethods.js]
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
__.prototype = b.prototype;
d.prototype = new __();
};
var A = (function () {
function A() {
}
A.prototype.isA = function () {
return true;
};
A.prototype.isC = function () {
return false;
};
return A;
})();
var B = (function () {
function B() {
}
B.prototype.isA = function () {
return false;
};
B.prototype.isC = function () {
return false;
};
return B;
})();
var C = (function (_super) {
__extends(C, _super);
function C() {
_super.apply(this, arguments);
}
C.prototype.isA = function () {
return false;
};
C.prototype.isC = function () {
return true;
};
return C;
})(A);
var D = (function (_super) {
__extends(D, _super);
function D() {
_super.apply(this, arguments);
}
D.prototype.isA = function () {
return false;
};
D.prototype.isString = function (x) {
return true;
};
return D;
})(C);
var a;
// Basic.
if (a.isC()) {
a.propC;
}
// Sub type.
var subType;
if (subType.isA()) {
subType.propC;
}
// Union type.
var union;
if (union.isA()) {
union.propA;
}
var b;
var d = new D;
if (d.isString(b)) {
b.length;
}

View file

@ -1,64 +0,0 @@
class A {
propA: number;
isA(): this is A {
return true;
}
isC(): this is C {
return false;
}
}
class B {
propB: number;
isA(): this is A {
return false;
}
isC(): this is C {
return false;
}
}
class C extends A {
propC: number;
isA(): this is A {
return false;
}
isC(): this is C {
return true;
}
}
class D extends C {
isA(): this is A {
return false;
}
isString(x: any): x is string { // with parameter declaration
return true;
}
}
var a: A;
// Basic.
if (a.isC()) {
a.propC;
}
// Sub type.
var subType: C;
if(subType.isA()) {
subType.propC;
}
// Union type.
var union: A | B;
if(union.isA()) {
union.propA;
}
var b: any;
var d = new D;
if(d.isString(b)) {
b.length;
}