From 002bb6f04b5fb7fecf8decf1c331d07b222b27e5 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 27 Oct 2015 15:23:38 -0700 Subject: [PATCH 001/274] Added tests. --- .../matchable/equalityWithUnionTypes01.ts | 20 +++++++++++++++ .../matchable/switchCaseWithUnionTypes01.ts | 25 +++++++++++++++++++ .../typeAssertionsWithUnionTypes01.ts | 16 ++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 tests/cases/conformance/types/typeRelationships/matchable/equalityWithUnionTypes01.ts create mode 100644 tests/cases/conformance/types/typeRelationships/matchable/switchCaseWithUnionTypes01.ts create mode 100644 tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithUnionTypes01.ts diff --git a/tests/cases/conformance/types/typeRelationships/matchable/equalityWithUnionTypes01.ts b/tests/cases/conformance/types/typeRelationships/matchable/equalityWithUnionTypes01.ts new file mode 100644 index 00000000000..d83277b975a --- /dev/null +++ b/tests/cases/conformance/types/typeRelationships/matchable/equalityWithUnionTypes01.ts @@ -0,0 +1,20 @@ +interface I1 { + p1: number +} + +interface I2 extends I1 { + p2: number; +} + +var x = { p1: 10, p2: 20 }; +var y: number | I2 = x; +var z: I1 = x; + +if (y === z || z === y) { +} +else if (y !== z || z !== y) { +} +else if (y == z || z == y) { +} +else if (y != z || z != y) { +} \ No newline at end of file diff --git a/tests/cases/conformance/types/typeRelationships/matchable/switchCaseWithUnionTypes01.ts b/tests/cases/conformance/types/typeRelationships/matchable/switchCaseWithUnionTypes01.ts new file mode 100644 index 00000000000..bdbfaf2df47 --- /dev/null +++ b/tests/cases/conformance/types/typeRelationships/matchable/switchCaseWithUnionTypes01.ts @@ -0,0 +1,25 @@ + +var strOrNum: string | number; +var numOrBool: number | boolean; +var str: string; +var num: number; +var bool: boolean; + +switch (strOrNum) { + // Identical + case strOrNum: + break; + + // Constituents + case str: + case num: + break; + + // Overlap in constituents + case numOrBool: + break; + + // No relation + case bool: + break; +} \ No newline at end of file diff --git a/tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithUnionTypes01.ts b/tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithUnionTypes01.ts new file mode 100644 index 00000000000..3010c5f159a --- /dev/null +++ b/tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithUnionTypes01.ts @@ -0,0 +1,16 @@ +interface I1 { + p1: number +} + +interface I2 extends I1 { + p2: number; +} + +var x = { p1: 10, p2: 20 }; +var y: number | I2 = x; +var z: I1 = x; + +var a = z; +var b = z; +var c = z; +var d = y; From 7426aca392e1d62c6e9985e2cd6909bc9432be80 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 27 Oct 2015 15:23:51 -0700 Subject: [PATCH 002/274] Accepted baselines. --- .../equalityWithUnionTypes01.errors.txt | 47 ++++++++++++++++++ .../reference/equalityWithUnionTypes01.js | 34 +++++++++++++ .../switchCaseWithUnionTypes01.errors.txt | 40 ++++++++++++++++ .../reference/switchCaseWithUnionTypes01.js | 48 +++++++++++++++++++ .../typeAssertionsWithUnionTypes01.errors.txt | 35 ++++++++++++++ .../typeAssertionsWithUnionTypes01.js | 27 +++++++++++ 6 files changed, 231 insertions(+) create mode 100644 tests/baselines/reference/equalityWithUnionTypes01.errors.txt create mode 100644 tests/baselines/reference/equalityWithUnionTypes01.js create mode 100644 tests/baselines/reference/switchCaseWithUnionTypes01.errors.txt create mode 100644 tests/baselines/reference/switchCaseWithUnionTypes01.js create mode 100644 tests/baselines/reference/typeAssertionsWithUnionTypes01.errors.txt create mode 100644 tests/baselines/reference/typeAssertionsWithUnionTypes01.js diff --git a/tests/baselines/reference/equalityWithUnionTypes01.errors.txt b/tests/baselines/reference/equalityWithUnionTypes01.errors.txt new file mode 100644 index 00000000000..985ba9e5867 --- /dev/null +++ b/tests/baselines/reference/equalityWithUnionTypes01.errors.txt @@ -0,0 +1,47 @@ +tests/cases/conformance/types/typeRelationships/matchable/equalityWithUnionTypes01.ts(13,5): error TS2365: Operator '===' cannot be applied to types 'number | I2' and 'I1'. +tests/cases/conformance/types/typeRelationships/matchable/equalityWithUnionTypes01.ts(13,16): error TS2365: Operator '===' cannot be applied to types 'I1' and 'number | I2'. +tests/cases/conformance/types/typeRelationships/matchable/equalityWithUnionTypes01.ts(15,10): error TS2365: Operator '!==' cannot be applied to types 'number | I2' and 'I1'. +tests/cases/conformance/types/typeRelationships/matchable/equalityWithUnionTypes01.ts(15,21): error TS2365: Operator '!==' cannot be applied to types 'I1' and 'number | I2'. +tests/cases/conformance/types/typeRelationships/matchable/equalityWithUnionTypes01.ts(17,10): error TS2365: Operator '==' cannot be applied to types 'number | I2' and 'I1'. +tests/cases/conformance/types/typeRelationships/matchable/equalityWithUnionTypes01.ts(17,20): error TS2365: Operator '==' cannot be applied to types 'I1' and 'number | I2'. +tests/cases/conformance/types/typeRelationships/matchable/equalityWithUnionTypes01.ts(19,10): error TS2365: Operator '!=' cannot be applied to types 'number | I2' and 'I1'. +tests/cases/conformance/types/typeRelationships/matchable/equalityWithUnionTypes01.ts(19,20): error TS2365: Operator '!=' cannot be applied to types 'I1' and 'number | I2'. + + +==== tests/cases/conformance/types/typeRelationships/matchable/equalityWithUnionTypes01.ts (8 errors) ==== + interface I1 { + p1: number + } + + interface I2 extends I1 { + p2: number; + } + + var x = { p1: 10, p2: 20 }; + var y: number | I2 = x; + var z: I1 = x; + + if (y === z || z === y) { + ~~~~~~~ +!!! error TS2365: Operator '===' cannot be applied to types 'number | I2' and 'I1'. + ~~~~~~~ +!!! error TS2365: Operator '===' cannot be applied to types 'I1' and 'number | I2'. + } + else if (y !== z || z !== y) { + ~~~~~~~ +!!! error TS2365: Operator '!==' cannot be applied to types 'number | I2' and 'I1'. + ~~~~~~~ +!!! error TS2365: Operator '!==' cannot be applied to types 'I1' and 'number | I2'. + } + else if (y == z || z == y) { + ~~~~~~ +!!! error TS2365: Operator '==' cannot be applied to types 'number | I2' and 'I1'. + ~~~~~~ +!!! error TS2365: Operator '==' cannot be applied to types 'I1' and 'number | I2'. + } + else if (y != z || z != y) { + ~~~~~~ +!!! error TS2365: Operator '!=' cannot be applied to types 'number | I2' and 'I1'. + ~~~~~~ +!!! error TS2365: Operator '!=' cannot be applied to types 'I1' and 'number | I2'. + } \ No newline at end of file diff --git a/tests/baselines/reference/equalityWithUnionTypes01.js b/tests/baselines/reference/equalityWithUnionTypes01.js new file mode 100644 index 00000000000..05e9f25cd69 --- /dev/null +++ b/tests/baselines/reference/equalityWithUnionTypes01.js @@ -0,0 +1,34 @@ +//// [equalityWithUnionTypes01.ts] +interface I1 { + p1: number +} + +interface I2 extends I1 { + p2: number; +} + +var x = { p1: 10, p2: 20 }; +var y: number | I2 = x; +var z: I1 = x; + +if (y === z || z === y) { +} +else if (y !== z || z !== y) { +} +else if (y == z || z == y) { +} +else if (y != z || z != y) { +} + +//// [equalityWithUnionTypes01.js] +var x = { p1: 10, p2: 20 }; +var y = x; +var z = x; +if (y === z || z === y) { +} +else if (y !== z || z !== y) { +} +else if (y == z || z == y) { +} +else if (y != z || z != y) { +} diff --git a/tests/baselines/reference/switchCaseWithUnionTypes01.errors.txt b/tests/baselines/reference/switchCaseWithUnionTypes01.errors.txt new file mode 100644 index 00000000000..ee60c210253 --- /dev/null +++ b/tests/baselines/reference/switchCaseWithUnionTypes01.errors.txt @@ -0,0 +1,40 @@ +tests/cases/conformance/types/typeRelationships/matchable/switchCaseWithUnionTypes01.ts(19,10): error TS2322: Type 'number | boolean' is not assignable to type 'string | number'. + Type 'boolean' is not assignable to type 'string | number'. + Type 'boolean' is not assignable to type 'number'. +tests/cases/conformance/types/typeRelationships/matchable/switchCaseWithUnionTypes01.ts(23,10): error TS2322: Type 'boolean' is not assignable to type 'string | number'. + Type 'boolean' is not assignable to type 'number'. + + +==== tests/cases/conformance/types/typeRelationships/matchable/switchCaseWithUnionTypes01.ts (2 errors) ==== + + var strOrNum: string | number; + var numOrBool: number | boolean; + var str: string; + var num: number; + var bool: boolean; + + switch (strOrNum) { + // Identical + case strOrNum: + break; + + // Constituents + case str: + case num: + break; + + // Overlap in constituents + case numOrBool: + ~~~~~~~~~ +!!! error TS2322: Type 'number | boolean' is not assignable to type 'string | number'. +!!! error TS2322: Type 'boolean' is not assignable to type 'string | number'. +!!! error TS2322: Type 'boolean' is not assignable to type 'number'. + break; + + // No relation + case bool: + ~~~~ +!!! error TS2322: Type 'boolean' is not assignable to type 'string | number'. +!!! error TS2322: Type 'boolean' is not assignable to type 'number'. + break; + } \ No newline at end of file diff --git a/tests/baselines/reference/switchCaseWithUnionTypes01.js b/tests/baselines/reference/switchCaseWithUnionTypes01.js new file mode 100644 index 00000000000..5c34ea674dc --- /dev/null +++ b/tests/baselines/reference/switchCaseWithUnionTypes01.js @@ -0,0 +1,48 @@ +//// [switchCaseWithUnionTypes01.ts] + +var strOrNum: string | number; +var numOrBool: number | boolean; +var str: string; +var num: number; +var bool: boolean; + +switch (strOrNum) { + // Identical + case strOrNum: + break; + + // Constituents + case str: + case num: + break; + + // Overlap in constituents + case numOrBool: + break; + + // No relation + case bool: + break; +} + +//// [switchCaseWithUnionTypes01.js] +var strOrNum; +var numOrBool; +var str; +var num; +var bool; +switch (strOrNum) { + // Identical + case strOrNum: + break; + // Constituents + case str: + case num: + break; + // Overlap in constituents + case numOrBool: + break; + // No relation + case bool: + break; +} diff --git a/tests/baselines/reference/typeAssertionsWithUnionTypes01.errors.txt b/tests/baselines/reference/typeAssertionsWithUnionTypes01.errors.txt new file mode 100644 index 00000000000..2a9dceaf8a6 --- /dev/null +++ b/tests/baselines/reference/typeAssertionsWithUnionTypes01.errors.txt @@ -0,0 +1,35 @@ +tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithUnionTypes01.ts(13,9): error TS2352: Neither type 'I1' nor type 'number | I2' is assignable to the other. + Type 'I1' is not assignable to type 'I2'. + Property 'p2' is missing in type 'I1'. +tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithUnionTypes01.ts(14,9): error TS2352: Neither type 'I1' nor type 'number' is assignable to the other. +tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithUnionTypes01.ts(16,9): error TS2352: Neither type 'number | I2' nor type 'I1' is assignable to the other. + Type 'number' is not assignable to type 'I1'. + + +==== tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithUnionTypes01.ts (3 errors) ==== + interface I1 { + p1: number + } + + interface I2 extends I1 { + p2: number; + } + + var x = { p1: 10, p2: 20 }; + var y: number | I2 = x; + var z: I1 = x; + + var a = z; + ~~~~~~~~~~~~~~ +!!! error TS2352: Neither type 'I1' nor type 'number | I2' is assignable to the other. +!!! error TS2352: Type 'I1' is not assignable to type 'I2'. +!!! error TS2352: Property 'p2' is missing in type 'I1'. + var b = z; + ~~~~~~~~~ +!!! error TS2352: Neither type 'I1' nor type 'number' is assignable to the other. + var c = z; + var d = y; + ~~~~~ +!!! error TS2352: Neither type 'number | I2' nor type 'I1' is assignable to the other. +!!! error TS2352: Type 'number' is not assignable to type 'I1'. + \ No newline at end of file diff --git a/tests/baselines/reference/typeAssertionsWithUnionTypes01.js b/tests/baselines/reference/typeAssertionsWithUnionTypes01.js new file mode 100644 index 00000000000..9cc448f6217 --- /dev/null +++ b/tests/baselines/reference/typeAssertionsWithUnionTypes01.js @@ -0,0 +1,27 @@ +//// [typeAssertionsWithUnionTypes01.ts] +interface I1 { + p1: number +} + +interface I2 extends I1 { + p2: number; +} + +var x = { p1: 10, p2: 20 }; +var y: number | I2 = x; +var z: I1 = x; + +var a = z; +var b = z; +var c = z; +var d = y; + + +//// [typeAssertionsWithUnionTypes01.js] +var x = { p1: 10, p2: 20 }; +var y = x; +var z = x; +var a = z; +var b = z; +var c = z; +var d = y; From 43f158d4185ce3432edadee7aefc299dc641435b Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 27 Oct 2015 16:17:26 -0700 Subject: [PATCH 003/274] Added "comparability" relation. It's currently equivalent to assignability. --- src/compiler/checker.ts | 47 +++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f64c25217bd..cebbe9380e3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -211,6 +211,7 @@ namespace ts { let subtypeRelation: Map = {}; let assignableRelation: Map = {}; + let comparableRelation: Map = {}; let identityRelation: Map = {}; // This is for caching the result of getSymbolDisplayBuilder. Do not access directly. @@ -4738,6 +4739,14 @@ namespace ts { return checkTypeAssignableTo(source, target, /*errorNode*/ undefined); } + /** + * This is *not* a bi-directional relationship. + * If one needs to check both directions for comparability, use a second call to this function or 'checkTypeComparableTo'. + */ + function isTypeComparableTo(source: Type, target: Type): boolean { + return checkTypeComparableTo(source, target, /*errorNode*/ undefined); + } + function checkTypeSubtypeOf(source: Type, target: Type, errorNode: Node, headMessage?: DiagnosticMessage, containingMessageChain?: DiagnosticMessageChain): boolean { return checkTypeRelatedTo(source, target, subtypeRelation, errorNode, headMessage, containingMessageChain); } @@ -4746,6 +4755,14 @@ namespace ts { return checkTypeRelatedTo(source, target, assignableRelation, errorNode, headMessage, containingMessageChain); } + /** + * This is *not* a bi-directional relationship. + * If one needs to check both directions for comparability, use a second call to this function or 'isTypeComparableTo'. + */ + function checkTypeComparableTo(source: Type, target: Type, errorNode: Node, headMessage?: DiagnosticMessage, containingMessageChain?: DiagnosticMessageChain): boolean { + return checkTypeRelatedTo(source, target, comparableRelation, errorNode, headMessage, containingMessageChain); + } + function isSignatureAssignableTo(source: Signature, target: Signature): boolean { let sourceType = getOrCreateTypeFromSignature(source); let targetType = getOrCreateTypeFromSignature(target); @@ -4756,7 +4773,7 @@ namespace ts { * Checks if 'source' is related to 'target' (e.g.: is a assignable to). * @param source The left-hand-side of the relation. * @param target The right-hand-side of the relation. - * @param relation The relation considered. One of 'identityRelation', 'assignableRelation', or 'subTypeRelation'. + * @param relation The relation considered. One of 'identityRelation', 'assignableRelation', 'subTypeRelation', or 'comparableRelation'. * Used as both to determine which checks are performed and as a cache of previously computed results. * @param errorNode The suggested node upon which all errors will be reported, if defined. This may or may not be the actual node used. * @param headMessage If the error chain should be prepended by a head message, then headMessage will be used. @@ -4781,6 +4798,7 @@ namespace ts { Debug.assert(relation !== identityRelation || !errorNode, "no error reporting in identity checking"); + const isAssignableOrComparableRelation = relation === assignableRelation || relation === comparableRelation; let result = isRelatedTo(source, target, errorNode !== undefined, headMessage); if (overflow) { error(errorNode, Diagnostics.Excessive_stack_depth_comparing_types_0_and_1, typeToString(source), typeToString(target)); @@ -4834,7 +4852,7 @@ namespace ts { if (source === nullType && target !== undefinedType) return Ternary.True; if (source.flags & TypeFlags.Enum && target === numberType) return Ternary.True; if (source.flags & TypeFlags.StringLiteral && target === stringType) return Ternary.True; - if (relation === assignableRelation) { + if (isAssignableOrComparableRelation) { if (isTypeAny(source)) return Ternary.True; if (source === numberType && target.flags & TypeFlags.Enum) return Ternary.True; } @@ -4942,8 +4960,8 @@ namespace ts { } if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union || source.flags & TypeFlags.Intersection && target.flags & TypeFlags.Intersection) { - if (result = eachTypeRelatedToSomeType(source, target)) { - if (result &= eachTypeRelatedToSomeType(target, source)) { + if (result = eachTypeRelatedToSomeType(source, target, /*reportErrors*/ false)) { + if (result &= eachTypeRelatedToSomeType(target, source, /*reportErrors*/ false)) { return result; } } @@ -4958,7 +4976,7 @@ namespace ts { function isKnownProperty(type: Type, name: string): boolean { if (type.flags & TypeFlags.ObjectType) { const resolved = resolveStructuredTypeMembers(type); - if (relation === assignableRelation && (type === globalObjectType || resolved.properties.length === 0) || + if (isAssignableOrComparableRelation && (type === globalObjectType || resolved.properties.length === 0) || resolved.stringIndexType || resolved.numberIndexType || getPropertyOfType(type, name)) { return true; } @@ -4992,11 +5010,11 @@ namespace ts { return false; } - function eachTypeRelatedToSomeType(source: UnionOrIntersectionType, target: UnionOrIntersectionType): Ternary { + function eachTypeRelatedToSomeType(source: UnionOrIntersectionType, target: UnionOrIntersectionType, reportErrors: boolean): Ternary { let result = Ternary.True; let sourceTypes = source.types; for (let sourceType of sourceTypes) { - let related = typeRelatedToSomeType(sourceType, target, false); + let related = typeRelatedToSomeType(sourceType, target, reportErrors); if (!related) { return Ternary.False; } @@ -9381,8 +9399,9 @@ namespace ts { let targetType = getTypeFromTypeNode(node.type); if (produceDiagnostics && targetType !== unknownType) { let widenedType = getWidenedType(exprType); - if (!(isTypeAssignableTo(targetType, widenedType))) { - checkTypeAssignableTo(exprType, targetType, node, Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other); + + if (!isTypeComparableTo(targetType, widenedType)) { + checkTypeComparableTo(exprType, targetType, node, Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other); } } return targetType; @@ -10225,7 +10244,7 @@ namespace ts { case SyntaxKind.ExclamationEqualsToken: case SyntaxKind.EqualsEqualsEqualsToken: case SyntaxKind.ExclamationEqualsEqualsToken: - if (!isTypeAssignableTo(leftType, rightType) && !isTypeAssignableTo(rightType, leftType)) { + if (!isTypeComparableTo(leftType, rightType) && !isTypeComparableTo(rightType, leftType)) { reportOperatorError(); } return booleanType; @@ -12689,12 +12708,12 @@ namespace ts { if (produceDiagnostics && clause.kind === SyntaxKind.CaseClause) { let caseClause = clause; - // TypeScript 1.0 spec (April 2014):5.9 + // TypeScript 1.0 spec (April 2014): 5.9 // In a 'switch' statement, each 'case' expression must be of a type that is assignable to or from the type of the 'switch' expression. let caseType = checkExpression(caseClause.expression); - if (!isTypeAssignableTo(expressionType, caseType)) { - // check 'expressionType isAssignableTo caseType' failed, try the reversed check and report errors if it fails - checkTypeAssignableTo(caseType, expressionType, caseClause.expression, /*headMessage*/ undefined); + + if (!isTypeComparableTo(expressionType, caseType)) { + checkTypeComparableTo(caseType, expressionType, caseClause.expression, /*headMessage*/ undefined); } } forEach(clause.statements, checkSourceElement); From 1edb007acc899879488cecd850241c384dfb92a5 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 27 Oct 2015 17:00:28 -0700 Subject: [PATCH 004/274] Check for partial satisfiability when using the comparable relationship. --- src/compiler/checker.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cebbe9380e3..52a9d6db1e7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4877,11 +4877,17 @@ namespace ts { // Note that the "each" checks must precede the "some" checks to produce the correct results if (source.flags & TypeFlags.Union) { + if (relation === comparableRelation && (result = someTypeRelatedToType(source as UnionType, target, reportErrors))) { + return result; + } if (result = eachTypeRelatedToType(source, target, reportErrors)) { return result; } } else if (target.flags & TypeFlags.Intersection) { + if (relation === comparableRelation && (result = typeRelatedToSomeType(source, target as IntersectionType, reportErrors))) { + return result; + } if (result = typeRelatedToEachType(source, target, reportErrors)) { return result; } From 9a5e3e3498e4d381df146c21abf7cd3d0e9ad8b1 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 27 Oct 2015 23:53:17 -0700 Subject: [PATCH 005/274] Avoid a redundant stricter check when using the new relation. --- src/compiler/checker.ts | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 52a9d6db1e7..c976b92b5a4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4877,18 +4877,26 @@ namespace ts { // Note that the "each" checks must precede the "some" checks to produce the correct results if (source.flags & TypeFlags.Union) { - if (relation === comparableRelation && (result = someTypeRelatedToType(source as UnionType, target, reportErrors))) { - return result; + if (relation === comparableRelation) { + result = someTypeRelatedToType(source as UnionType, target, reportErrors); } - if (result = eachTypeRelatedToType(source, target, reportErrors)) { + else { + result = eachTypeRelatedToType(source, target, reportErrors); + } + + if (result) { return result; } } else if (target.flags & TypeFlags.Intersection) { - if (relation === comparableRelation && (result = typeRelatedToSomeType(source, target as IntersectionType, reportErrors))) { - return result; + if (relation === comparableRelation) { + result = typeRelatedToSomeType(source, target as IntersectionType, reportErrors); } - if (result = typeRelatedToEachType(source, target, reportErrors)) { + else { + result = typeRelatedToEachType(source, target, reportErrors); + } + + if (result) { return result; } } @@ -4897,7 +4905,8 @@ namespace ts { // on either side that need to be prioritized. For example, A | B = (A | B) & (C | D) or // A & B = (A & B) | (C & D). if (source.flags & TypeFlags.Intersection) { - // If target is a union type the following check will report errors so we suppress them here + // If target is a union type then the check following this one will report errors, + // so we'll suppress any errors we could run into here. if (result = someTypeRelatedToType(source, target, reportErrors && !(target.flags & TypeFlags.Union))) { return result; } From 42b3ce4d0c6a7b8ac5e89136ce54a6ed01f699e4 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 27 Oct 2015 23:58:24 -0700 Subject: [PATCH 006/274] Rename the relationship to "matchable by". --- src/compiler/checker.ts | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c976b92b5a4..02ecc43aa4d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -211,7 +211,7 @@ namespace ts { let subtypeRelation: Map = {}; let assignableRelation: Map = {}; - let comparableRelation: Map = {}; + let matchableRelation: Map = {}; let identityRelation: Map = {}; // This is for caching the result of getSymbolDisplayBuilder. Do not access directly. @@ -4743,8 +4743,8 @@ namespace ts { * This is *not* a bi-directional relationship. * If one needs to check both directions for comparability, use a second call to this function or 'checkTypeComparableTo'. */ - function isTypeComparableTo(source: Type, target: Type): boolean { - return checkTypeComparableTo(source, target, /*errorNode*/ undefined); + function isTypeMatchableBy(source: Type, target: Type): boolean { + return checkTypeMatchableBy(source, target, /*errorNode*/ undefined); } function checkTypeSubtypeOf(source: Type, target: Type, errorNode: Node, headMessage?: DiagnosticMessage, containingMessageChain?: DiagnosticMessageChain): boolean { @@ -4757,10 +4757,10 @@ namespace ts { /** * This is *not* a bi-directional relationship. - * If one needs to check both directions for comparability, use a second call to this function or 'isTypeComparableTo'. + * If one needs to check both directions for comparability, use a second call to this function or 'isTypeMatchableBy'. */ - function checkTypeComparableTo(source: Type, target: Type, errorNode: Node, headMessage?: DiagnosticMessage, containingMessageChain?: DiagnosticMessageChain): boolean { - return checkTypeRelatedTo(source, target, comparableRelation, errorNode, headMessage, containingMessageChain); + function checkTypeMatchableBy(source: Type, target: Type, errorNode: Node, headMessage?: DiagnosticMessage, containingMessageChain?: DiagnosticMessageChain): boolean { + return checkTypeRelatedTo(source, target, matchableRelation, errorNode, headMessage, containingMessageChain); } function isSignatureAssignableTo(source: Signature, target: Signature): boolean { @@ -4773,7 +4773,7 @@ namespace ts { * Checks if 'source' is related to 'target' (e.g.: is a assignable to). * @param source The left-hand-side of the relation. * @param target The right-hand-side of the relation. - * @param relation The relation considered. One of 'identityRelation', 'assignableRelation', 'subTypeRelation', or 'comparableRelation'. + * @param relation The relation considered. One of 'identityRelation', 'assignableRelation', 'subTypeRelation', or 'matchableRelation'. * Used as both to determine which checks are performed and as a cache of previously computed results. * @param errorNode The suggested node upon which all errors will be reported, if defined. This may or may not be the actual node used. * @param headMessage If the error chain should be prepended by a head message, then headMessage will be used. @@ -4798,7 +4798,7 @@ namespace ts { Debug.assert(relation !== identityRelation || !errorNode, "no error reporting in identity checking"); - const isAssignableOrComparableRelation = relation === assignableRelation || relation === comparableRelation; + const isAssignableOrComparableRelation = relation === assignableRelation || relation === matchableRelation; let result = isRelatedTo(source, target, errorNode !== undefined, headMessage); if (overflow) { error(errorNode, Diagnostics.Excessive_stack_depth_comparing_types_0_and_1, typeToString(source), typeToString(target)); @@ -4877,7 +4877,7 @@ namespace ts { // Note that the "each" checks must precede the "some" checks to produce the correct results if (source.flags & TypeFlags.Union) { - if (relation === comparableRelation) { + if (relation === matchableRelation) { result = someTypeRelatedToType(source as UnionType, target, reportErrors); } else { @@ -4889,7 +4889,7 @@ namespace ts { } } else if (target.flags & TypeFlags.Intersection) { - if (relation === comparableRelation) { + if (relation === matchableRelation) { result = typeRelatedToSomeType(source, target as IntersectionType, reportErrors); } else { @@ -9415,8 +9415,8 @@ namespace ts { if (produceDiagnostics && targetType !== unknownType) { let widenedType = getWidenedType(exprType); - if (!isTypeComparableTo(targetType, widenedType)) { - checkTypeComparableTo(exprType, targetType, node, Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other); + if (!isTypeMatchableBy(targetType, widenedType)) { + checkTypeMatchableBy(exprType, targetType, node, Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other); } } return targetType; @@ -10259,7 +10259,7 @@ namespace ts { case SyntaxKind.ExclamationEqualsToken: case SyntaxKind.EqualsEqualsEqualsToken: case SyntaxKind.ExclamationEqualsEqualsToken: - if (!isTypeComparableTo(leftType, rightType) && !isTypeComparableTo(rightType, leftType)) { + if (!isTypeMatchableBy(leftType, rightType) && !isTypeMatchableBy(rightType, leftType)) { reportOperatorError(); } return booleanType; @@ -12727,8 +12727,8 @@ namespace ts { // In a 'switch' statement, each 'case' expression must be of a type that is assignable to or from the type of the 'switch' expression. let caseType = checkExpression(caseClause.expression); - if (!isTypeComparableTo(expressionType, caseType)) { - checkTypeComparableTo(caseType, expressionType, caseClause.expression, /*headMessage*/ undefined); + if (!isTypeMatchableBy(expressionType, caseType)) { + checkTypeMatchableBy(caseType, expressionType, caseClause.expression, /*headMessage*/ undefined); } } forEach(clause.statements, checkSourceElement); From 929808ef07eb6b394a1a8ea5802f31ed4c7eff7e Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 28 Oct 2015 17:09:27 -0700 Subject: [PATCH 007/274] Accepted baselines. --- .../reference/castingTuple.errors.txt | 23 +----- .../equalityWithUnionTypes01.errors.txt | 47 ------------- .../equalityWithUnionTypes01.symbols | 55 +++++++++++++++ .../reference/equalityWithUnionTypes01.types | 70 +++++++++++++++++++ .../switchCaseWithUnionTypes01.errors.txt | 9 +-- .../typeAssertionsWithUnionTypes01.errors.txt | 14 +--- 6 files changed, 128 insertions(+), 90 deletions(-) delete mode 100644 tests/baselines/reference/equalityWithUnionTypes01.errors.txt create mode 100644 tests/baselines/reference/equalityWithUnionTypes01.symbols create mode 100644 tests/baselines/reference/equalityWithUnionTypes01.types diff --git a/tests/baselines/reference/castingTuple.errors.txt b/tests/baselines/reference/castingTuple.errors.txt index 62a36c9c156..128ee5b5bb4 100644 --- a/tests/baselines/reference/castingTuple.errors.txt +++ b/tests/baselines/reference/castingTuple.errors.txt @@ -1,7 +1,3 @@ -tests/cases/conformance/types/tuple/castingTuple.ts(13,23): error TS2352: Neither type '[number, string]' nor type '[number, string, boolean]' is assignable to the other. - Property '2' is missing in type '[number, string]'. -tests/cases/conformance/types/tuple/castingTuple.ts(16,21): error TS2352: Neither type '[C, D]' nor type '[C, D, A]' is assignable to the other. - Property '2' is missing in type '[C, D]'. tests/cases/conformance/types/tuple/castingTuple.ts(28,10): error TS2352: Neither type '[number, string]' nor type '[number, number]' is assignable to the other. Types of property '1' are incompatible. Type 'string' is not assignable to type 'number'. @@ -10,15 +6,10 @@ tests/cases/conformance/types/tuple/castingTuple.ts(29,10): error TS2352: Neithe Type 'C' is not assignable to type 'A'. Property 'a' is missing in type 'C'. tests/cases/conformance/types/tuple/castingTuple.ts(30,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'array1' must be of type '{}[]', but here has type 'number[]'. -tests/cases/conformance/types/tuple/castingTuple.ts(30,14): error TS2352: Neither type '[number, string]' nor type 'number[]' is assignable to the other. - Types of property 'pop' are incompatible. - Type '() => number | string' is not assignable to type '() => number'. - Type 'number | string' is not assignable to type 'number'. - Type 'string' is not assignable to type 'number'. tests/cases/conformance/types/tuple/castingTuple.ts(31,1): error TS2304: Cannot find name 't4'. -==== tests/cases/conformance/types/tuple/castingTuple.ts (7 errors) ==== +==== tests/cases/conformance/types/tuple/castingTuple.ts (4 errors) ==== interface I { } class A { a = 10; } class C implements I { c }; @@ -32,15 +23,9 @@ tests/cases/conformance/types/tuple/castingTuple.ts(31,1): error TS2304: Cannot var numStrTuple: [number, string] = [5, "foo"]; var emptyObjTuple = <[{}, {}]>numStrTuple; var numStrBoolTuple = <[number, string, boolean]>numStrTuple; - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2352: Neither type '[number, string]' nor type '[number, string, boolean]' is assignable to the other. -!!! error TS2352: Property '2' is missing in type '[number, string]'. var classCDTuple: [C, D] = [new C(), new D()]; var interfaceIITuple = <[I, I]>classCDTuple; var classCDATuple = <[C, D, A]>classCDTuple; - ~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2352: Neither type '[C, D]' nor type '[C, D, A]' is assignable to the other. -!!! error TS2352: Property '2' is missing in type '[C, D]'. var eleFromCDA1 = classCDATuple[2]; // A var eleFromCDA2 = classCDATuple[5]; // C | D | A var t10: [E1, E2] = [E1.one, E2.one]; @@ -66,12 +51,6 @@ tests/cases/conformance/types/tuple/castingTuple.ts(31,1): error TS2304: Cannot var array1 = numStrTuple; ~~~~~~ !!! error TS2403: Subsequent variable declarations must have the same type. Variable 'array1' must be of type '{}[]', but here has type 'number[]'. - ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2352: Neither type '[number, string]' nor type 'number[]' is assignable to the other. -!!! error TS2352: Types of property 'pop' are incompatible. -!!! error TS2352: Type '() => number | string' is not assignable to type '() => number'. -!!! error TS2352: Type 'number | string' is not assignable to type 'number'. -!!! error TS2352: Type 'string' is not assignable to type 'number'. t4[2] = 10; ~~ !!! error TS2304: Cannot find name 't4'. diff --git a/tests/baselines/reference/equalityWithUnionTypes01.errors.txt b/tests/baselines/reference/equalityWithUnionTypes01.errors.txt deleted file mode 100644 index 985ba9e5867..00000000000 --- a/tests/baselines/reference/equalityWithUnionTypes01.errors.txt +++ /dev/null @@ -1,47 +0,0 @@ -tests/cases/conformance/types/typeRelationships/matchable/equalityWithUnionTypes01.ts(13,5): error TS2365: Operator '===' cannot be applied to types 'number | I2' and 'I1'. -tests/cases/conformance/types/typeRelationships/matchable/equalityWithUnionTypes01.ts(13,16): error TS2365: Operator '===' cannot be applied to types 'I1' and 'number | I2'. -tests/cases/conformance/types/typeRelationships/matchable/equalityWithUnionTypes01.ts(15,10): error TS2365: Operator '!==' cannot be applied to types 'number | I2' and 'I1'. -tests/cases/conformance/types/typeRelationships/matchable/equalityWithUnionTypes01.ts(15,21): error TS2365: Operator '!==' cannot be applied to types 'I1' and 'number | I2'. -tests/cases/conformance/types/typeRelationships/matchable/equalityWithUnionTypes01.ts(17,10): error TS2365: Operator '==' cannot be applied to types 'number | I2' and 'I1'. -tests/cases/conformance/types/typeRelationships/matchable/equalityWithUnionTypes01.ts(17,20): error TS2365: Operator '==' cannot be applied to types 'I1' and 'number | I2'. -tests/cases/conformance/types/typeRelationships/matchable/equalityWithUnionTypes01.ts(19,10): error TS2365: Operator '!=' cannot be applied to types 'number | I2' and 'I1'. -tests/cases/conformance/types/typeRelationships/matchable/equalityWithUnionTypes01.ts(19,20): error TS2365: Operator '!=' cannot be applied to types 'I1' and 'number | I2'. - - -==== tests/cases/conformance/types/typeRelationships/matchable/equalityWithUnionTypes01.ts (8 errors) ==== - interface I1 { - p1: number - } - - interface I2 extends I1 { - p2: number; - } - - var x = { p1: 10, p2: 20 }; - var y: number | I2 = x; - var z: I1 = x; - - if (y === z || z === y) { - ~~~~~~~ -!!! error TS2365: Operator '===' cannot be applied to types 'number | I2' and 'I1'. - ~~~~~~~ -!!! error TS2365: Operator '===' cannot be applied to types 'I1' and 'number | I2'. - } - else if (y !== z || z !== y) { - ~~~~~~~ -!!! error TS2365: Operator '!==' cannot be applied to types 'number | I2' and 'I1'. - ~~~~~~~ -!!! error TS2365: Operator '!==' cannot be applied to types 'I1' and 'number | I2'. - } - else if (y == z || z == y) { - ~~~~~~ -!!! error TS2365: Operator '==' cannot be applied to types 'number | I2' and 'I1'. - ~~~~~~ -!!! error TS2365: Operator '==' cannot be applied to types 'I1' and 'number | I2'. - } - else if (y != z || z != y) { - ~~~~~~ -!!! error TS2365: Operator '!=' cannot be applied to types 'number | I2' and 'I1'. - ~~~~~~ -!!! error TS2365: Operator '!=' cannot be applied to types 'I1' and 'number | I2'. - } \ No newline at end of file diff --git a/tests/baselines/reference/equalityWithUnionTypes01.symbols b/tests/baselines/reference/equalityWithUnionTypes01.symbols new file mode 100644 index 00000000000..2baf5034f77 --- /dev/null +++ b/tests/baselines/reference/equalityWithUnionTypes01.symbols @@ -0,0 +1,55 @@ +=== tests/cases/conformance/types/typeRelationships/matchable/equalityWithUnionTypes01.ts === +interface I1 { +>I1 : Symbol(I1, Decl(equalityWithUnionTypes01.ts, 0, 0)) + + p1: number +>p1 : Symbol(p1, Decl(equalityWithUnionTypes01.ts, 0, 14)) +} + +interface I2 extends I1 { +>I2 : Symbol(I2, Decl(equalityWithUnionTypes01.ts, 2, 1)) +>I1 : Symbol(I1, Decl(equalityWithUnionTypes01.ts, 0, 0)) + + p2: number; +>p2 : Symbol(p2, Decl(equalityWithUnionTypes01.ts, 4, 25)) +} + +var x = { p1: 10, p2: 20 }; +>x : Symbol(x, Decl(equalityWithUnionTypes01.ts, 8, 3)) +>p1 : Symbol(p1, Decl(equalityWithUnionTypes01.ts, 8, 9)) +>p2 : Symbol(p2, Decl(equalityWithUnionTypes01.ts, 8, 17)) + +var y: number | I2 = x; +>y : Symbol(y, Decl(equalityWithUnionTypes01.ts, 9, 3)) +>I2 : Symbol(I2, Decl(equalityWithUnionTypes01.ts, 2, 1)) +>x : Symbol(x, Decl(equalityWithUnionTypes01.ts, 8, 3)) + +var z: I1 = x; +>z : Symbol(z, Decl(equalityWithUnionTypes01.ts, 10, 3)) +>I1 : Symbol(I1, Decl(equalityWithUnionTypes01.ts, 0, 0)) +>x : Symbol(x, Decl(equalityWithUnionTypes01.ts, 8, 3)) + +if (y === z || z === y) { +>y : Symbol(y, Decl(equalityWithUnionTypes01.ts, 9, 3)) +>z : Symbol(z, Decl(equalityWithUnionTypes01.ts, 10, 3)) +>z : Symbol(z, Decl(equalityWithUnionTypes01.ts, 10, 3)) +>y : Symbol(y, Decl(equalityWithUnionTypes01.ts, 9, 3)) +} +else if (y !== z || z !== y) { +>y : Symbol(y, Decl(equalityWithUnionTypes01.ts, 9, 3)) +>z : Symbol(z, Decl(equalityWithUnionTypes01.ts, 10, 3)) +>z : Symbol(z, Decl(equalityWithUnionTypes01.ts, 10, 3)) +>y : Symbol(y, Decl(equalityWithUnionTypes01.ts, 9, 3)) +} +else if (y == z || z == y) { +>y : Symbol(y, Decl(equalityWithUnionTypes01.ts, 9, 3)) +>z : Symbol(z, Decl(equalityWithUnionTypes01.ts, 10, 3)) +>z : Symbol(z, Decl(equalityWithUnionTypes01.ts, 10, 3)) +>y : Symbol(y, Decl(equalityWithUnionTypes01.ts, 9, 3)) +} +else if (y != z || z != y) { +>y : Symbol(y, Decl(equalityWithUnionTypes01.ts, 9, 3)) +>z : Symbol(z, Decl(equalityWithUnionTypes01.ts, 10, 3)) +>z : Symbol(z, Decl(equalityWithUnionTypes01.ts, 10, 3)) +>y : Symbol(y, Decl(equalityWithUnionTypes01.ts, 9, 3)) +} diff --git a/tests/baselines/reference/equalityWithUnionTypes01.types b/tests/baselines/reference/equalityWithUnionTypes01.types new file mode 100644 index 00000000000..e6a5ce487d9 --- /dev/null +++ b/tests/baselines/reference/equalityWithUnionTypes01.types @@ -0,0 +1,70 @@ +=== tests/cases/conformance/types/typeRelationships/matchable/equalityWithUnionTypes01.ts === +interface I1 { +>I1 : I1 + + p1: number +>p1 : number +} + +interface I2 extends I1 { +>I2 : I2 +>I1 : I1 + + p2: number; +>p2 : number +} + +var x = { p1: 10, p2: 20 }; +>x : { p1: number; p2: number; } +>{ p1: 10, p2: 20 } : { p1: number; p2: number; } +>p1 : number +>10 : number +>p2 : number +>20 : number + +var y: number | I2 = x; +>y : number | I2 +>I2 : I2 +>x : { p1: number; p2: number; } + +var z: I1 = x; +>z : I1 +>I1 : I1 +>x : { p1: number; p2: number; } + +if (y === z || z === y) { +>y === z || z === y : boolean +>y === z : boolean +>y : number | I2 +>z : I1 +>z === y : boolean +>z : I1 +>y : number | I2 +} +else if (y !== z || z !== y) { +>y !== z || z !== y : boolean +>y !== z : boolean +>y : number | I2 +>z : I1 +>z !== y : boolean +>z : I1 +>y : number | I2 +} +else if (y == z || z == y) { +>y == z || z == y : boolean +>y == z : boolean +>y : number | I2 +>z : I1 +>z == y : boolean +>z : I1 +>y : number | I2 +} +else if (y != z || z != y) { +>y != z || z != y : boolean +>y != z : boolean +>y : number | I2 +>z : I1 +>z != y : boolean +>z : I1 +>y : number | I2 +} diff --git a/tests/baselines/reference/switchCaseWithUnionTypes01.errors.txt b/tests/baselines/reference/switchCaseWithUnionTypes01.errors.txt index ee60c210253..a59c9ec57f7 100644 --- a/tests/baselines/reference/switchCaseWithUnionTypes01.errors.txt +++ b/tests/baselines/reference/switchCaseWithUnionTypes01.errors.txt @@ -1,11 +1,8 @@ -tests/cases/conformance/types/typeRelationships/matchable/switchCaseWithUnionTypes01.ts(19,10): error TS2322: Type 'number | boolean' is not assignable to type 'string | number'. - Type 'boolean' is not assignable to type 'string | number'. - Type 'boolean' is not assignable to type 'number'. tests/cases/conformance/types/typeRelationships/matchable/switchCaseWithUnionTypes01.ts(23,10): error TS2322: Type 'boolean' is not assignable to type 'string | number'. Type 'boolean' is not assignable to type 'number'. -==== tests/cases/conformance/types/typeRelationships/matchable/switchCaseWithUnionTypes01.ts (2 errors) ==== +==== tests/cases/conformance/types/typeRelationships/matchable/switchCaseWithUnionTypes01.ts (1 errors) ==== var strOrNum: string | number; var numOrBool: number | boolean; @@ -25,10 +22,6 @@ tests/cases/conformance/types/typeRelationships/matchable/switchCaseWithUnionTyp // Overlap in constituents case numOrBool: - ~~~~~~~~~ -!!! error TS2322: Type 'number | boolean' is not assignable to type 'string | number'. -!!! error TS2322: Type 'boolean' is not assignable to type 'string | number'. -!!! error TS2322: Type 'boolean' is not assignable to type 'number'. break; // No relation diff --git a/tests/baselines/reference/typeAssertionsWithUnionTypes01.errors.txt b/tests/baselines/reference/typeAssertionsWithUnionTypes01.errors.txt index 2a9dceaf8a6..022617c8ba0 100644 --- a/tests/baselines/reference/typeAssertionsWithUnionTypes01.errors.txt +++ b/tests/baselines/reference/typeAssertionsWithUnionTypes01.errors.txt @@ -1,12 +1,7 @@ -tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithUnionTypes01.ts(13,9): error TS2352: Neither type 'I1' nor type 'number | I2' is assignable to the other. - Type 'I1' is not assignable to type 'I2'. - Property 'p2' is missing in type 'I1'. tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithUnionTypes01.ts(14,9): error TS2352: Neither type 'I1' nor type 'number' is assignable to the other. -tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithUnionTypes01.ts(16,9): error TS2352: Neither type 'number | I2' nor type 'I1' is assignable to the other. - Type 'number' is not assignable to type 'I1'. -==== tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithUnionTypes01.ts (3 errors) ==== +==== tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithUnionTypes01.ts (1 errors) ==== interface I1 { p1: number } @@ -20,16 +15,9 @@ tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithUnio var z: I1 = x; var a = z; - ~~~~~~~~~~~~~~ -!!! error TS2352: Neither type 'I1' nor type 'number | I2' is assignable to the other. -!!! error TS2352: Type 'I1' is not assignable to type 'I2'. -!!! error TS2352: Property 'p2' is missing in type 'I1'. var b = z; ~~~~~~~~~ !!! error TS2352: Neither type 'I1' nor type 'number' is assignable to the other. var c = z; var d = y; - ~~~~~ -!!! error TS2352: Neither type 'number | I2' nor type 'I1' is assignable to the other. -!!! error TS2352: Type 'number' is not assignable to type 'I1'. \ No newline at end of file From 262352ec5bd8514edcfbeaacaff31664b37b6aef Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 28 Oct 2015 16:09:45 -0700 Subject: [PATCH 008/274] Added tests on intersection types. --- .../equalityWithIntersectionTypes01.ts | 24 ++++++++++++++++++ .../switchCaseWithIntersectionTypes01.ts | 25 +++++++++++++++++++ .../typeAssertionsWithIntersectionTypes01.ts | 20 +++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 tests/cases/conformance/types/typeRelationships/matchable/equalityWithIntersectionTypes01.ts create mode 100644 tests/cases/conformance/types/typeRelationships/matchable/switchCaseWithIntersectionTypes01.ts create mode 100644 tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithIntersectionTypes01.ts diff --git a/tests/cases/conformance/types/typeRelationships/matchable/equalityWithIntersectionTypes01.ts b/tests/cases/conformance/types/typeRelationships/matchable/equalityWithIntersectionTypes01.ts new file mode 100644 index 00000000000..74c0ebb7412 --- /dev/null +++ b/tests/cases/conformance/types/typeRelationships/matchable/equalityWithIntersectionTypes01.ts @@ -0,0 +1,24 @@ +interface I1 { + p1: number +} + +interface I2 extends I1 { + p2: number; +} + +interface I3 { + p3: number; +} + +var x = { p1: 10, p2: 20, p3: 30 }; +var y: I1 & I3 = x; +var z: I2 = x; + +if (y === z || z === y) { +} +else if (y !== z || z !== y) { +} +else if (y == z || z == y) { +} +else if (y != z || z != y) { +} \ No newline at end of file diff --git a/tests/cases/conformance/types/typeRelationships/matchable/switchCaseWithIntersectionTypes01.ts b/tests/cases/conformance/types/typeRelationships/matchable/switchCaseWithIntersectionTypes01.ts new file mode 100644 index 00000000000..fd629306b10 --- /dev/null +++ b/tests/cases/conformance/types/typeRelationships/matchable/switchCaseWithIntersectionTypes01.ts @@ -0,0 +1,25 @@ + +var strAndNum: string & number; +var numAndBool: number & boolean; +var str: string; +var num: number; +var bool: boolean; + +switch (strAndNum) { + // Identical + case strAndNum: + break; + + // Constituents + case str: + case num: + break; + + // Overlap in constituents + case numAndBool: + break; + + // No relation + case bool: + break; +} \ No newline at end of file diff --git a/tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithIntersectionTypes01.ts b/tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithIntersectionTypes01.ts new file mode 100644 index 00000000000..1afc760ef85 --- /dev/null +++ b/tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithIntersectionTypes01.ts @@ -0,0 +1,20 @@ +interface I1 { + p1: number +} + +interface I2 extends I1 { + p2: number; +} + +interface I3 { + p3: number; +} + +var x = { p1: 10, p2: 20, p3: 30 }; +var y: I1 & I3 = x; +var z: I2 = x; + +var a = z; +var b = z; +var c = z; +var d = y; From bdb1db5ae4576e0a1f2472352e7c9e537150556e Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 28 Oct 2015 16:11:14 -0700 Subject: [PATCH 009/274] Matchable should have no effect on intersections. --- src/compiler/checker.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 02ecc43aa4d..3e2b6a7317f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4889,12 +4889,7 @@ namespace ts { } } else if (target.flags & TypeFlags.Intersection) { - if (relation === matchableRelation) { - result = typeRelatedToSomeType(source, target as IntersectionType, reportErrors); - } - else { - result = typeRelatedToEachType(source, target, reportErrors); - } + result = typeRelatedToEachType(source, target, reportErrors); if (result) { return result; From 441dd78114f6e64f43f5a9c94d89e6df18758786 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 28 Oct 2015 17:10:02 -0700 Subject: [PATCH 010/274] Accepted baselines. --- ...equalityWithIntersectionTypes01.errors.txt | 51 +++++++++++++++++++ .../equalityWithIntersectionTypes01.js | 38 ++++++++++++++ ...itchCaseWithIntersectionTypes01.errors.txt | 40 +++++++++++++++ .../switchCaseWithIntersectionTypes01.js | 48 +++++++++++++++++ ...sertionsWithIntersectionTypes01.errors.txt | 34 +++++++++++++ .../typeAssertionsWithIntersectionTypes01.js | 31 +++++++++++ 6 files changed, 242 insertions(+) create mode 100644 tests/baselines/reference/equalityWithIntersectionTypes01.errors.txt create mode 100644 tests/baselines/reference/equalityWithIntersectionTypes01.js create mode 100644 tests/baselines/reference/switchCaseWithIntersectionTypes01.errors.txt create mode 100644 tests/baselines/reference/switchCaseWithIntersectionTypes01.js create mode 100644 tests/baselines/reference/typeAssertionsWithIntersectionTypes01.errors.txt create mode 100644 tests/baselines/reference/typeAssertionsWithIntersectionTypes01.js diff --git a/tests/baselines/reference/equalityWithIntersectionTypes01.errors.txt b/tests/baselines/reference/equalityWithIntersectionTypes01.errors.txt new file mode 100644 index 00000000000..da18a774204 --- /dev/null +++ b/tests/baselines/reference/equalityWithIntersectionTypes01.errors.txt @@ -0,0 +1,51 @@ +tests/cases/conformance/types/typeRelationships/matchable/equalityWithIntersectionTypes01.ts(17,5): error TS2365: Operator '===' cannot be applied to types 'I1 & I3' and 'I2'. +tests/cases/conformance/types/typeRelationships/matchable/equalityWithIntersectionTypes01.ts(17,16): error TS2365: Operator '===' cannot be applied to types 'I2' and 'I1 & I3'. +tests/cases/conformance/types/typeRelationships/matchable/equalityWithIntersectionTypes01.ts(19,10): error TS2365: Operator '!==' cannot be applied to types 'I1 & I3' and 'I2'. +tests/cases/conformance/types/typeRelationships/matchable/equalityWithIntersectionTypes01.ts(19,21): error TS2365: Operator '!==' cannot be applied to types 'I2' and 'I1 & I3'. +tests/cases/conformance/types/typeRelationships/matchable/equalityWithIntersectionTypes01.ts(21,10): error TS2365: Operator '==' cannot be applied to types 'I1 & I3' and 'I2'. +tests/cases/conformance/types/typeRelationships/matchable/equalityWithIntersectionTypes01.ts(21,20): error TS2365: Operator '==' cannot be applied to types 'I2' and 'I1 & I3'. +tests/cases/conformance/types/typeRelationships/matchable/equalityWithIntersectionTypes01.ts(23,10): error TS2365: Operator '!=' cannot be applied to types 'I1 & I3' and 'I2'. +tests/cases/conformance/types/typeRelationships/matchable/equalityWithIntersectionTypes01.ts(23,20): error TS2365: Operator '!=' cannot be applied to types 'I2' and 'I1 & I3'. + + +==== tests/cases/conformance/types/typeRelationships/matchable/equalityWithIntersectionTypes01.ts (8 errors) ==== + interface I1 { + p1: number + } + + interface I2 extends I1 { + p2: number; + } + + interface I3 { + p3: number; + } + + var x = { p1: 10, p2: 20, p3: 30 }; + var y: I1 & I3 = x; + var z: I2 = x; + + if (y === z || z === y) { + ~~~~~~~ +!!! error TS2365: Operator '===' cannot be applied to types 'I1 & I3' and 'I2'. + ~~~~~~~ +!!! error TS2365: Operator '===' cannot be applied to types 'I2' and 'I1 & I3'. + } + else if (y !== z || z !== y) { + ~~~~~~~ +!!! error TS2365: Operator '!==' cannot be applied to types 'I1 & I3' and 'I2'. + ~~~~~~~ +!!! error TS2365: Operator '!==' cannot be applied to types 'I2' and 'I1 & I3'. + } + else if (y == z || z == y) { + ~~~~~~ +!!! error TS2365: Operator '==' cannot be applied to types 'I1 & I3' and 'I2'. + ~~~~~~ +!!! error TS2365: Operator '==' cannot be applied to types 'I2' and 'I1 & I3'. + } + else if (y != z || z != y) { + ~~~~~~ +!!! error TS2365: Operator '!=' cannot be applied to types 'I1 & I3' and 'I2'. + ~~~~~~ +!!! error TS2365: Operator '!=' cannot be applied to types 'I2' and 'I1 & I3'. + } \ No newline at end of file diff --git a/tests/baselines/reference/equalityWithIntersectionTypes01.js b/tests/baselines/reference/equalityWithIntersectionTypes01.js new file mode 100644 index 00000000000..151809bb6f8 --- /dev/null +++ b/tests/baselines/reference/equalityWithIntersectionTypes01.js @@ -0,0 +1,38 @@ +//// [equalityWithIntersectionTypes01.ts] +interface I1 { + p1: number +} + +interface I2 extends I1 { + p2: number; +} + +interface I3 { + p3: number; +} + +var x = { p1: 10, p2: 20, p3: 30 }; +var y: I1 & I3 = x; +var z: I2 = x; + +if (y === z || z === y) { +} +else if (y !== z || z !== y) { +} +else if (y == z || z == y) { +} +else if (y != z || z != y) { +} + +//// [equalityWithIntersectionTypes01.js] +var x = { p1: 10, p2: 20, p3: 30 }; +var y = x; +var z = x; +if (y === z || z === y) { +} +else if (y !== z || z !== y) { +} +else if (y == z || z == y) { +} +else if (y != z || z != y) { +} diff --git a/tests/baselines/reference/switchCaseWithIntersectionTypes01.errors.txt b/tests/baselines/reference/switchCaseWithIntersectionTypes01.errors.txt new file mode 100644 index 00000000000..5c2e8ad30fe --- /dev/null +++ b/tests/baselines/reference/switchCaseWithIntersectionTypes01.errors.txt @@ -0,0 +1,40 @@ +tests/cases/conformance/types/typeRelationships/matchable/switchCaseWithIntersectionTypes01.ts(19,10): error TS2322: Type 'number & boolean' is not assignable to type 'string & number'. + Type 'number & boolean' is not assignable to type 'string'. + Type 'boolean' is not assignable to type 'string'. +tests/cases/conformance/types/typeRelationships/matchable/switchCaseWithIntersectionTypes01.ts(23,10): error TS2322: Type 'boolean' is not assignable to type 'string & number'. + Type 'boolean' is not assignable to type 'string'. + + +==== tests/cases/conformance/types/typeRelationships/matchable/switchCaseWithIntersectionTypes01.ts (2 errors) ==== + + var strAndNum: string & number; + var numAndBool: number & boolean; + var str: string; + var num: number; + var bool: boolean; + + switch (strAndNum) { + // Identical + case strAndNum: + break; + + // Constituents + case str: + case num: + break; + + // Overlap in constituents + case numAndBool: + ~~~~~~~~~~ +!!! error TS2322: Type 'number & boolean' is not assignable to type 'string & number'. +!!! error TS2322: Type 'number & boolean' is not assignable to type 'string'. +!!! error TS2322: Type 'boolean' is not assignable to type 'string'. + break; + + // No relation + case bool: + ~~~~ +!!! error TS2322: Type 'boolean' is not assignable to type 'string & number'. +!!! error TS2322: Type 'boolean' is not assignable to type 'string'. + break; + } \ No newline at end of file diff --git a/tests/baselines/reference/switchCaseWithIntersectionTypes01.js b/tests/baselines/reference/switchCaseWithIntersectionTypes01.js new file mode 100644 index 00000000000..4e0ddf7ea76 --- /dev/null +++ b/tests/baselines/reference/switchCaseWithIntersectionTypes01.js @@ -0,0 +1,48 @@ +//// [switchCaseWithIntersectionTypes01.ts] + +var strAndNum: string & number; +var numAndBool: number & boolean; +var str: string; +var num: number; +var bool: boolean; + +switch (strAndNum) { + // Identical + case strAndNum: + break; + + // Constituents + case str: + case num: + break; + + // Overlap in constituents + case numAndBool: + break; + + // No relation + case bool: + break; +} + +//// [switchCaseWithIntersectionTypes01.js] +var strAndNum; +var numAndBool; +var str; +var num; +var bool; +switch (strAndNum) { + // Identical + case strAndNum: + break; + // Constituents + case str: + case num: + break; + // Overlap in constituents + case numAndBool: + break; + // No relation + case bool: + break; +} diff --git a/tests/baselines/reference/typeAssertionsWithIntersectionTypes01.errors.txt b/tests/baselines/reference/typeAssertionsWithIntersectionTypes01.errors.txt new file mode 100644 index 00000000000..b5041f6fe55 --- /dev/null +++ b/tests/baselines/reference/typeAssertionsWithIntersectionTypes01.errors.txt @@ -0,0 +1,34 @@ +tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithIntersectionTypes01.ts(17,9): error TS2352: Neither type 'I2' nor type 'I1 & I3' is assignable to the other. + Type 'I2' is not assignable to type 'I3'. + Property 'p3' is missing in type 'I2'. +tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithIntersectionTypes01.ts(18,9): error TS2352: Neither type 'I2' nor type 'I3' is assignable to the other. + + +==== tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithIntersectionTypes01.ts (2 errors) ==== + interface I1 { + p1: number + } + + interface I2 extends I1 { + p2: number; + } + + interface I3 { + p3: number; + } + + var x = { p1: 10, p2: 20, p3: 30 }; + var y: I1 & I3 = x; + var z: I2 = x; + + var a = z; + ~~~~~~~~~~ +!!! error TS2352: Neither type 'I2' nor type 'I1 & I3' is assignable to the other. +!!! error TS2352: Type 'I2' is not assignable to type 'I3'. +!!! error TS2352: Property 'p3' is missing in type 'I2'. + var b = z; + ~~~~~ +!!! error TS2352: Neither type 'I2' nor type 'I3' is assignable to the other. + var c = z; + var d = y; + \ No newline at end of file diff --git a/tests/baselines/reference/typeAssertionsWithIntersectionTypes01.js b/tests/baselines/reference/typeAssertionsWithIntersectionTypes01.js new file mode 100644 index 00000000000..31fc831f95f --- /dev/null +++ b/tests/baselines/reference/typeAssertionsWithIntersectionTypes01.js @@ -0,0 +1,31 @@ +//// [typeAssertionsWithIntersectionTypes01.ts] +interface I1 { + p1: number +} + +interface I2 extends I1 { + p2: number; +} + +interface I3 { + p3: number; +} + +var x = { p1: 10, p2: 20, p3: 30 }; +var y: I1 & I3 = x; +var z: I2 = x; + +var a = z; +var b = z; +var c = z; +var d = y; + + +//// [typeAssertionsWithIntersectionTypes01.js] +var x = { p1: 10, p2: 20, p3: 30 }; +var y = x; +var z = x; +var a = z; +var b = z; +var c = z; +var d = y; From 841789d162e91f6a88e1db411b7bd22ffc6e23f2 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 29 Oct 2015 16:36:25 -0700 Subject: [PATCH 011/274] Renamed the relationship back to "comparable". --- src/compiler/checker.ts | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3e2b6a7317f..ac44a748d6c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -211,7 +211,7 @@ namespace ts { let subtypeRelation: Map = {}; let assignableRelation: Map = {}; - let matchableRelation: Map = {}; + let comparableRelation: Map = {}; let identityRelation: Map = {}; // This is for caching the result of getSymbolDisplayBuilder. Do not access directly. @@ -4743,8 +4743,8 @@ namespace ts { * This is *not* a bi-directional relationship. * If one needs to check both directions for comparability, use a second call to this function or 'checkTypeComparableTo'. */ - function isTypeMatchableBy(source: Type, target: Type): boolean { - return checkTypeMatchableBy(source, target, /*errorNode*/ undefined); + function isTypeComparableTo(source: Type, target: Type): boolean { + return checkTypeComparableTo(source, target, /*errorNode*/ undefined); } function checkTypeSubtypeOf(source: Type, target: Type, errorNode: Node, headMessage?: DiagnosticMessage, containingMessageChain?: DiagnosticMessageChain): boolean { @@ -4757,10 +4757,10 @@ namespace ts { /** * This is *not* a bi-directional relationship. - * If one needs to check both directions for comparability, use a second call to this function or 'isTypeMatchableBy'. + * If one needs to check both directions for comparability, use a second call to this function or 'isTypeComparableTo'. */ - function checkTypeMatchableBy(source: Type, target: Type, errorNode: Node, headMessage?: DiagnosticMessage, containingMessageChain?: DiagnosticMessageChain): boolean { - return checkTypeRelatedTo(source, target, matchableRelation, errorNode, headMessage, containingMessageChain); + function checkTypeComparableTo(source: Type, target: Type, errorNode: Node, headMessage?: DiagnosticMessage, containingMessageChain?: DiagnosticMessageChain): boolean { + return checkTypeRelatedTo(source, target, comparableRelation, errorNode, headMessage, containingMessageChain); } function isSignatureAssignableTo(source: Signature, target: Signature): boolean { @@ -4773,7 +4773,7 @@ namespace ts { * Checks if 'source' is related to 'target' (e.g.: is a assignable to). * @param source The left-hand-side of the relation. * @param target The right-hand-side of the relation. - * @param relation The relation considered. One of 'identityRelation', 'assignableRelation', 'subTypeRelation', or 'matchableRelation'. + * @param relation The relation considered. One of 'identityRelation', 'assignableRelation', 'subTypeRelation', or 'comparableRelation'. * Used as both to determine which checks are performed and as a cache of previously computed results. * @param errorNode The suggested node upon which all errors will be reported, if defined. This may or may not be the actual node used. * @param headMessage If the error chain should be prepended by a head message, then headMessage will be used. @@ -4798,7 +4798,7 @@ namespace ts { Debug.assert(relation !== identityRelation || !errorNode, "no error reporting in identity checking"); - const isAssignableOrComparableRelation = relation === assignableRelation || relation === matchableRelation; + const isAssignableOrComparableRelation = relation === assignableRelation || relation === comparableRelation; let result = isRelatedTo(source, target, errorNode !== undefined, headMessage); if (overflow) { error(errorNode, Diagnostics.Excessive_stack_depth_comparing_types_0_and_1, typeToString(source), typeToString(target)); @@ -4877,7 +4877,7 @@ namespace ts { // Note that the "each" checks must precede the "some" checks to produce the correct results if (source.flags & TypeFlags.Union) { - if (relation === matchableRelation) { + if (relation === comparableRelation) { result = someTypeRelatedToType(source as UnionType, target, reportErrors); } else { @@ -9410,8 +9410,8 @@ namespace ts { if (produceDiagnostics && targetType !== unknownType) { let widenedType = getWidenedType(exprType); - if (!isTypeMatchableBy(targetType, widenedType)) { - checkTypeMatchableBy(exprType, targetType, node, Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other); + if (!isTypeComparableTo(targetType, widenedType)) { + checkTypeComparableTo(exprType, targetType, node, Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other); } } return targetType; @@ -10254,7 +10254,7 @@ namespace ts { case SyntaxKind.ExclamationEqualsToken: case SyntaxKind.EqualsEqualsEqualsToken: case SyntaxKind.ExclamationEqualsEqualsToken: - if (!isTypeMatchableBy(leftType, rightType) && !isTypeMatchableBy(rightType, leftType)) { + if (!isTypeComparableTo(leftType, rightType) && !isTypeComparableTo(rightType, leftType)) { reportOperatorError(); } return booleanType; @@ -12722,8 +12722,8 @@ namespace ts { // In a 'switch' statement, each 'case' expression must be of a type that is assignable to or from the type of the 'switch' expression. let caseType = checkExpression(caseClause.expression); - if (!isTypeMatchableBy(expressionType, caseType)) { - checkTypeMatchableBy(caseType, expressionType, caseClause.expression, /*headMessage*/ undefined); + if (!isTypeComparableTo(expressionType, caseType)) { + checkTypeComparableTo(caseType, expressionType, caseClause.expression, /*headMessage*/ undefined); } } forEach(clause.statements, checkSourceElement); From 5cb95d4044aefb378c6ee85f939bb625f697518f Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 29 Oct 2015 16:40:34 -0700 Subject: [PATCH 012/274] Renamed test directory. --- .../{matchable => comparable}/equalityWithIntersectionTypes01.ts | 0 .../{matchable => comparable}/equalityWithUnionTypes01.ts | 0 .../switchCaseWithIntersectionTypes01.ts | 0 .../{matchable => comparable}/switchCaseWithUnionTypes01.ts | 0 .../typeAssertionsWithIntersectionTypes01.ts | 0 .../{matchable => comparable}/typeAssertionsWithUnionTypes01.ts | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename tests/cases/conformance/types/typeRelationships/{matchable => comparable}/equalityWithIntersectionTypes01.ts (100%) rename tests/cases/conformance/types/typeRelationships/{matchable => comparable}/equalityWithUnionTypes01.ts (100%) rename tests/cases/conformance/types/typeRelationships/{matchable => comparable}/switchCaseWithIntersectionTypes01.ts (100%) rename tests/cases/conformance/types/typeRelationships/{matchable => comparable}/switchCaseWithUnionTypes01.ts (100%) rename tests/cases/conformance/types/typeRelationships/{matchable => comparable}/typeAssertionsWithIntersectionTypes01.ts (100%) rename tests/cases/conformance/types/typeRelationships/{matchable => comparable}/typeAssertionsWithUnionTypes01.ts (100%) diff --git a/tests/cases/conformance/types/typeRelationships/matchable/equalityWithIntersectionTypes01.ts b/tests/cases/conformance/types/typeRelationships/comparable/equalityWithIntersectionTypes01.ts similarity index 100% rename from tests/cases/conformance/types/typeRelationships/matchable/equalityWithIntersectionTypes01.ts rename to tests/cases/conformance/types/typeRelationships/comparable/equalityWithIntersectionTypes01.ts diff --git a/tests/cases/conformance/types/typeRelationships/matchable/equalityWithUnionTypes01.ts b/tests/cases/conformance/types/typeRelationships/comparable/equalityWithUnionTypes01.ts similarity index 100% rename from tests/cases/conformance/types/typeRelationships/matchable/equalityWithUnionTypes01.ts rename to tests/cases/conformance/types/typeRelationships/comparable/equalityWithUnionTypes01.ts diff --git a/tests/cases/conformance/types/typeRelationships/matchable/switchCaseWithIntersectionTypes01.ts b/tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithIntersectionTypes01.ts similarity index 100% rename from tests/cases/conformance/types/typeRelationships/matchable/switchCaseWithIntersectionTypes01.ts rename to tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithIntersectionTypes01.ts diff --git a/tests/cases/conformance/types/typeRelationships/matchable/switchCaseWithUnionTypes01.ts b/tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithUnionTypes01.ts similarity index 100% rename from tests/cases/conformance/types/typeRelationships/matchable/switchCaseWithUnionTypes01.ts rename to tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithUnionTypes01.ts diff --git a/tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithIntersectionTypes01.ts b/tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithIntersectionTypes01.ts similarity index 100% rename from tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithIntersectionTypes01.ts rename to tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithIntersectionTypes01.ts diff --git a/tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithUnionTypes01.ts b/tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithUnionTypes01.ts similarity index 100% rename from tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithUnionTypes01.ts rename to tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithUnionTypes01.ts From ab7c4e5e43077df3d1b090c6f3f4cae2b734e580 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 29 Oct 2015 16:40:54 -0700 Subject: [PATCH 013/274] Accepted baselines. --- .../equalityWithIntersectionTypes01.errors.txt | 18 +++++++++--------- .../reference/equalityWithUnionTypes01.symbols | 2 +- .../reference/equalityWithUnionTypes01.types | 2 +- ...witchCaseWithIntersectionTypes01.errors.txt | 6 +++--- .../switchCaseWithUnionTypes01.errors.txt | 4 ++-- ...ssertionsWithIntersectionTypes01.errors.txt | 6 +++--- .../typeAssertionsWithUnionTypes01.errors.txt | 4 ++-- 7 files changed, 21 insertions(+), 21 deletions(-) diff --git a/tests/baselines/reference/equalityWithIntersectionTypes01.errors.txt b/tests/baselines/reference/equalityWithIntersectionTypes01.errors.txt index da18a774204..8bffff2218b 100644 --- a/tests/baselines/reference/equalityWithIntersectionTypes01.errors.txt +++ b/tests/baselines/reference/equalityWithIntersectionTypes01.errors.txt @@ -1,14 +1,14 @@ -tests/cases/conformance/types/typeRelationships/matchable/equalityWithIntersectionTypes01.ts(17,5): error TS2365: Operator '===' cannot be applied to types 'I1 & I3' and 'I2'. -tests/cases/conformance/types/typeRelationships/matchable/equalityWithIntersectionTypes01.ts(17,16): error TS2365: Operator '===' cannot be applied to types 'I2' and 'I1 & I3'. -tests/cases/conformance/types/typeRelationships/matchable/equalityWithIntersectionTypes01.ts(19,10): error TS2365: Operator '!==' cannot be applied to types 'I1 & I3' and 'I2'. -tests/cases/conformance/types/typeRelationships/matchable/equalityWithIntersectionTypes01.ts(19,21): error TS2365: Operator '!==' cannot be applied to types 'I2' and 'I1 & I3'. -tests/cases/conformance/types/typeRelationships/matchable/equalityWithIntersectionTypes01.ts(21,10): error TS2365: Operator '==' cannot be applied to types 'I1 & I3' and 'I2'. -tests/cases/conformance/types/typeRelationships/matchable/equalityWithIntersectionTypes01.ts(21,20): error TS2365: Operator '==' cannot be applied to types 'I2' and 'I1 & I3'. -tests/cases/conformance/types/typeRelationships/matchable/equalityWithIntersectionTypes01.ts(23,10): error TS2365: Operator '!=' cannot be applied to types 'I1 & I3' and 'I2'. -tests/cases/conformance/types/typeRelationships/matchable/equalityWithIntersectionTypes01.ts(23,20): error TS2365: Operator '!=' cannot be applied to types 'I2' and 'I1 & I3'. +tests/cases/conformance/types/typeRelationships/comparable/equalityWithIntersectionTypes01.ts(17,5): error TS2365: Operator '===' cannot be applied to types 'I1 & I3' and 'I2'. +tests/cases/conformance/types/typeRelationships/comparable/equalityWithIntersectionTypes01.ts(17,16): error TS2365: Operator '===' cannot be applied to types 'I2' and 'I1 & I3'. +tests/cases/conformance/types/typeRelationships/comparable/equalityWithIntersectionTypes01.ts(19,10): error TS2365: Operator '!==' cannot be applied to types 'I1 & I3' and 'I2'. +tests/cases/conformance/types/typeRelationships/comparable/equalityWithIntersectionTypes01.ts(19,21): error TS2365: Operator '!==' cannot be applied to types 'I2' and 'I1 & I3'. +tests/cases/conformance/types/typeRelationships/comparable/equalityWithIntersectionTypes01.ts(21,10): error TS2365: Operator '==' cannot be applied to types 'I1 & I3' and 'I2'. +tests/cases/conformance/types/typeRelationships/comparable/equalityWithIntersectionTypes01.ts(21,20): error TS2365: Operator '==' cannot be applied to types 'I2' and 'I1 & I3'. +tests/cases/conformance/types/typeRelationships/comparable/equalityWithIntersectionTypes01.ts(23,10): error TS2365: Operator '!=' cannot be applied to types 'I1 & I3' and 'I2'. +tests/cases/conformance/types/typeRelationships/comparable/equalityWithIntersectionTypes01.ts(23,20): error TS2365: Operator '!=' cannot be applied to types 'I2' and 'I1 & I3'. -==== tests/cases/conformance/types/typeRelationships/matchable/equalityWithIntersectionTypes01.ts (8 errors) ==== +==== tests/cases/conformance/types/typeRelationships/comparable/equalityWithIntersectionTypes01.ts (8 errors) ==== interface I1 { p1: number } diff --git a/tests/baselines/reference/equalityWithUnionTypes01.symbols b/tests/baselines/reference/equalityWithUnionTypes01.symbols index 2baf5034f77..52332cf2e60 100644 --- a/tests/baselines/reference/equalityWithUnionTypes01.symbols +++ b/tests/baselines/reference/equalityWithUnionTypes01.symbols @@ -1,4 +1,4 @@ -=== tests/cases/conformance/types/typeRelationships/matchable/equalityWithUnionTypes01.ts === +=== tests/cases/conformance/types/typeRelationships/comparable/equalityWithUnionTypes01.ts === interface I1 { >I1 : Symbol(I1, Decl(equalityWithUnionTypes01.ts, 0, 0)) diff --git a/tests/baselines/reference/equalityWithUnionTypes01.types b/tests/baselines/reference/equalityWithUnionTypes01.types index e6a5ce487d9..27bf01c048b 100644 --- a/tests/baselines/reference/equalityWithUnionTypes01.types +++ b/tests/baselines/reference/equalityWithUnionTypes01.types @@ -1,4 +1,4 @@ -=== tests/cases/conformance/types/typeRelationships/matchable/equalityWithUnionTypes01.ts === +=== tests/cases/conformance/types/typeRelationships/comparable/equalityWithUnionTypes01.ts === interface I1 { >I1 : I1 diff --git a/tests/baselines/reference/switchCaseWithIntersectionTypes01.errors.txt b/tests/baselines/reference/switchCaseWithIntersectionTypes01.errors.txt index 5c2e8ad30fe..967a59071af 100644 --- a/tests/baselines/reference/switchCaseWithIntersectionTypes01.errors.txt +++ b/tests/baselines/reference/switchCaseWithIntersectionTypes01.errors.txt @@ -1,11 +1,11 @@ -tests/cases/conformance/types/typeRelationships/matchable/switchCaseWithIntersectionTypes01.ts(19,10): error TS2322: Type 'number & boolean' is not assignable to type 'string & number'. +tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithIntersectionTypes01.ts(19,10): error TS2322: Type 'number & boolean' is not assignable to type 'string & number'. Type 'number & boolean' is not assignable to type 'string'. Type 'boolean' is not assignable to type 'string'. -tests/cases/conformance/types/typeRelationships/matchable/switchCaseWithIntersectionTypes01.ts(23,10): error TS2322: Type 'boolean' is not assignable to type 'string & number'. +tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithIntersectionTypes01.ts(23,10): error TS2322: Type 'boolean' is not assignable to type 'string & number'. Type 'boolean' is not assignable to type 'string'. -==== tests/cases/conformance/types/typeRelationships/matchable/switchCaseWithIntersectionTypes01.ts (2 errors) ==== +==== tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithIntersectionTypes01.ts (2 errors) ==== var strAndNum: string & number; var numAndBool: number & boolean; diff --git a/tests/baselines/reference/switchCaseWithUnionTypes01.errors.txt b/tests/baselines/reference/switchCaseWithUnionTypes01.errors.txt index a59c9ec57f7..66f01cc1d34 100644 --- a/tests/baselines/reference/switchCaseWithUnionTypes01.errors.txt +++ b/tests/baselines/reference/switchCaseWithUnionTypes01.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/types/typeRelationships/matchable/switchCaseWithUnionTypes01.ts(23,10): error TS2322: Type 'boolean' is not assignable to type 'string | number'. +tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithUnionTypes01.ts(23,10): error TS2322: Type 'boolean' is not assignable to type 'string | number'. Type 'boolean' is not assignable to type 'number'. -==== tests/cases/conformance/types/typeRelationships/matchable/switchCaseWithUnionTypes01.ts (1 errors) ==== +==== tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithUnionTypes01.ts (1 errors) ==== var strOrNum: string | number; var numOrBool: number | boolean; diff --git a/tests/baselines/reference/typeAssertionsWithIntersectionTypes01.errors.txt b/tests/baselines/reference/typeAssertionsWithIntersectionTypes01.errors.txt index b5041f6fe55..162e55a225e 100644 --- a/tests/baselines/reference/typeAssertionsWithIntersectionTypes01.errors.txt +++ b/tests/baselines/reference/typeAssertionsWithIntersectionTypes01.errors.txt @@ -1,10 +1,10 @@ -tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithIntersectionTypes01.ts(17,9): error TS2352: Neither type 'I2' nor type 'I1 & I3' is assignable to the other. +tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithIntersectionTypes01.ts(17,9): error TS2352: Neither type 'I2' nor type 'I1 & I3' is assignable to the other. Type 'I2' is not assignable to type 'I3'. Property 'p3' is missing in type 'I2'. -tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithIntersectionTypes01.ts(18,9): error TS2352: Neither type 'I2' nor type 'I3' is assignable to the other. +tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithIntersectionTypes01.ts(18,9): error TS2352: Neither type 'I2' nor type 'I3' is assignable to the other. -==== tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithIntersectionTypes01.ts (2 errors) ==== +==== tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithIntersectionTypes01.ts (2 errors) ==== interface I1 { p1: number } diff --git a/tests/baselines/reference/typeAssertionsWithUnionTypes01.errors.txt b/tests/baselines/reference/typeAssertionsWithUnionTypes01.errors.txt index 022617c8ba0..68ab174ff98 100644 --- a/tests/baselines/reference/typeAssertionsWithUnionTypes01.errors.txt +++ b/tests/baselines/reference/typeAssertionsWithUnionTypes01.errors.txt @@ -1,7 +1,7 @@ -tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithUnionTypes01.ts(14,9): error TS2352: Neither type 'I1' nor type 'number' is assignable to the other. +tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithUnionTypes01.ts(14,9): error TS2352: Neither type 'I1' nor type 'number' is assignable to the other. -==== tests/cases/conformance/types/typeRelationships/matchable/typeAssertionsWithUnionTypes01.ts (1 errors) ==== +==== tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithUnionTypes01.ts (1 errors) ==== interface I1 { p1: number } From e224083038b15ecd20990bd4e4fb223c1928bc9e Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 3 Nov 2015 17:17:53 -0800 Subject: [PATCH 014/274] Updated error message. --- src/compiler/checker.ts | 11 +++++++++-- src/compiler/diagnosticMessages.json | 8 ++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ac44a748d6c..a804cacb7de 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4832,7 +4832,14 @@ namespace ts { sourceType = typeToString(source, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType); targetType = typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType); } - reportError(message || Diagnostics.Type_0_is_not_assignable_to_type_1, sourceType, targetType); + + if (!message) { + message = relation === comparableRelation ? + Diagnostics.Type_0_is_not_comparable_with_type_1 : + Diagnostics.Type_0_is_not_assignable_to_type_1 + } + + reportError(message, sourceType, targetType); } // Compare two types and return @@ -9411,7 +9418,7 @@ namespace ts { let widenedType = getWidenedType(exprType); if (!isTypeComparableTo(targetType, widenedType)) { - checkTypeComparableTo(exprType, targetType, node, Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other); + checkTypeComparableTo(exprType, targetType, node); } } return targetType; diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 4fdeb122983..4f1b4869918 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -888,6 +888,10 @@ "category": "Error", "code": 2322 }, + "Type '{0}' is not comparable with type '{1}'.": { + "category": "Error", + "code": 2323 + }, "Property '{0}' is missing in type '{1}'.": { "category": "Error", "code": 2324 @@ -996,10 +1000,6 @@ "category": "Error", "code": 2351 }, - "Neither type '{0}' nor type '{1}' is assignable to the other.": { - "category": "Error", - "code": 2352 - }, "Object literal may only specify known properties, and '{0}' does not exist in type '{1}'.": { "category": "Error", "code": 2353 From fa6e181ffaa3ac357f139f551cba71b8d004d70a Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 3 Nov 2015 17:29:27 -0800 Subject: [PATCH 015/274] Accepted baselines. --- .../baselines/reference/arrayCast.errors.txt | 10 ++++---- .../reference/asOperator2.errors.txt | 4 ++-- .../asOperatorContextualType.errors.txt | 8 +++---- .../reference/asOperatorNames.errors.txt | 4 ++-- .../reference/castingTuple.errors.txt | 22 ++++++++--------- .../reference/contextualTyping39.errors.txt | 8 +++---- .../reference/contextualTyping41.errors.txt | 8 +++---- ...efaultArgsInFunctionExpressions.errors.txt | 8 +++---- tests/baselines/reference/fuzzy.errors.txt | 6 ++--- .../genericTypeAssertions1.errors.txt | 8 +++---- .../genericTypeAssertions2.errors.txt | 6 ++--- .../genericTypeAssertions4.errors.txt | 8 +++---- .../genericTypeAssertions5.errors.txt | 8 +++---- .../genericTypeAssertions6.errors.txt | 16 ++++++------- .../reference/intTypeCheck.errors.txt | 4 ++-- .../reference/literals-negative.errors.txt | 4 ++-- .../noImplicitAnyInCastExpression.errors.txt | 6 ++--- ...bjectTypesIdentityWithPrivates3.errors.txt | 6 ++--- .../switchAssignmentCompat.errors.txt | 4 ++-- ...itchCaseWithIntersectionTypes01.errors.txt | 20 ++++++++-------- .../switchCaseWithUnionTypes01.errors.txt | 8 +++---- ...itchCasesExpressionTypeMismatch.errors.txt | 12 +++++----- .../reference/switchStatements.errors.txt | 6 ++--- .../reference/typeAssertions.errors.txt | 24 +++++++++---------- ...sertionsWithIntersectionTypes01.errors.txt | 14 +++++------ .../typeAssertionsWithUnionTypes01.errors.txt | 4 ++-- 26 files changed, 118 insertions(+), 118 deletions(-) diff --git a/tests/baselines/reference/arrayCast.errors.txt b/tests/baselines/reference/arrayCast.errors.txt index 815813ea727..c73f3ce879c 100644 --- a/tests/baselines/reference/arrayCast.errors.txt +++ b/tests/baselines/reference/arrayCast.errors.txt @@ -1,5 +1,5 @@ -tests/cases/compiler/arrayCast.ts(3,23): error TS2352: Neither type '{ foo: string; }[]' nor type '{ id: number; }[]' is assignable to the other. - Type '{ foo: string; }' is not assignable to type '{ id: number; }'. +tests/cases/compiler/arrayCast.ts(3,23): error TS2323: Type '{ foo: string; }[]' is not comparable with type '{ id: number; }[]'. + Type '{ foo: string; }' is not comparable with type '{ id: number; }'. Object literal may only specify known properties, and 'foo' does not exist in type '{ id: number; }'. @@ -8,9 +8,9 @@ tests/cases/compiler/arrayCast.ts(3,23): error TS2352: Neither type '{ foo: stri // has type { foo: string }[], which is not assignable to { id: number }[]. <{ id: number; }[]>[{ foo: "s" }]; ~~~~~~~~ -!!! error TS2352: Neither type '{ foo: string; }[]' nor type '{ id: number; }[]' is assignable to the other. -!!! error TS2352: Type '{ foo: string; }' is not assignable to type '{ id: number; }'. -!!! error TS2352: Object literal may only specify known properties, and 'foo' does not exist in type '{ id: number; }'. +!!! error TS2323: Type '{ foo: string; }[]' is not comparable with type '{ id: number; }[]'. +!!! error TS2323: Type '{ foo: string; }' is not comparable with type '{ id: number; }'. +!!! error TS2323: Object literal may only specify known properties, and 'foo' does not exist in type '{ id: number; }'. // Should succeed, as the {} element causes the type of the array to be {}[] <{ id: number; }[]>[{ foo: "s" }, {}]; \ No newline at end of file diff --git a/tests/baselines/reference/asOperator2.errors.txt b/tests/baselines/reference/asOperator2.errors.txt index 3b074038c26..d3eb568d79a 100644 --- a/tests/baselines/reference/asOperator2.errors.txt +++ b/tests/baselines/reference/asOperator2.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/expressions/asOperator/asOperator2.ts(1,9): error TS2352: Neither type 'number' nor type 'string' is assignable to the other. +tests/cases/conformance/expressions/asOperator/asOperator2.ts(1,9): error TS2323: Type 'number' is not comparable with type 'string'. ==== tests/cases/conformance/expressions/asOperator/asOperator2.ts (1 errors) ==== var x = 23 as string; ~~~~~~~~~~~~ -!!! error TS2352: Neither type 'number' nor type 'string' is assignable to the other. +!!! error TS2323: Type 'number' is not comparable with type 'string'. \ No newline at end of file diff --git a/tests/baselines/reference/asOperatorContextualType.errors.txt b/tests/baselines/reference/asOperatorContextualType.errors.txt index c53b407b5cf..a2ea2a7f83e 100644 --- a/tests/baselines/reference/asOperatorContextualType.errors.txt +++ b/tests/baselines/reference/asOperatorContextualType.errors.txt @@ -1,10 +1,10 @@ -tests/cases/conformance/expressions/asOperator/asOperatorContextualType.ts(2,9): error TS2352: Neither type '(v: number) => number' nor type '(x: number) => string' is assignable to the other. - Type 'number' is not assignable to type 'string'. +tests/cases/conformance/expressions/asOperator/asOperatorContextualType.ts(2,9): error TS2323: Type '(v: number) => number' is not comparable with type '(x: number) => string'. + Type 'number' is not comparable with type 'string'. ==== tests/cases/conformance/expressions/asOperator/asOperatorContextualType.ts (1 errors) ==== // should error var x = (v => v) as (x: number) => string; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2352: Neither type '(v: number) => number' nor type '(x: number) => string' is assignable to the other. -!!! error TS2352: Type 'number' is not assignable to type 'string'. \ No newline at end of file +!!! error TS2323: Type '(v: number) => number' is not comparable with type '(x: number) => string'. +!!! error TS2323: Type 'number' is not comparable with type 'string'. \ No newline at end of file diff --git a/tests/baselines/reference/asOperatorNames.errors.txt b/tests/baselines/reference/asOperatorNames.errors.txt index e3dfaab9884..61847f5dba1 100644 --- a/tests/baselines/reference/asOperatorNames.errors.txt +++ b/tests/baselines/reference/asOperatorNames.errors.txt @@ -1,11 +1,11 @@ -tests/cases/conformance/expressions/asOperator/asOperatorNames.ts(2,9): error TS2352: Neither type 'number' nor type 'string' is assignable to the other. +tests/cases/conformance/expressions/asOperator/asOperatorNames.ts(2,9): error TS2323: Type 'number' is not comparable with type 'string'. ==== tests/cases/conformance/expressions/asOperator/asOperatorNames.ts (1 errors) ==== var a = 20; var b = a as string; ~~~~~~~~~~~ -!!! error TS2352: Neither type 'number' nor type 'string' is assignable to the other. +!!! error TS2323: Type 'number' is not comparable with type 'string'. var as = "hello"; var as1 = as as string; \ No newline at end of file diff --git a/tests/baselines/reference/castingTuple.errors.txt b/tests/baselines/reference/castingTuple.errors.txt index 128ee5b5bb4..04caf8e22c5 100644 --- a/tests/baselines/reference/castingTuple.errors.txt +++ b/tests/baselines/reference/castingTuple.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/types/tuple/castingTuple.ts(28,10): error TS2352: Neither type '[number, string]' nor type '[number, number]' is assignable to the other. +tests/cases/conformance/types/tuple/castingTuple.ts(28,10): error TS2323: Type '[number, string]' is not comparable with type '[number, number]'. Types of property '1' are incompatible. - Type 'string' is not assignable to type 'number'. -tests/cases/conformance/types/tuple/castingTuple.ts(29,10): error TS2352: Neither type '[C, D]' nor type '[A, I]' is assignable to the other. + Type 'string' is not comparable with type 'number'. +tests/cases/conformance/types/tuple/castingTuple.ts(29,10): error TS2323: Type '[C, D]' is not comparable with type '[A, I]'. Types of property '0' are incompatible. - Type 'C' is not assignable to type 'A'. + Type 'C' is not comparable with type 'A'. Property 'a' is missing in type 'C'. tests/cases/conformance/types/tuple/castingTuple.ts(30,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'array1' must be of type '{}[]', but here has type 'number[]'. tests/cases/conformance/types/tuple/castingTuple.ts(31,1): error TS2304: Cannot find name 't4'. @@ -39,15 +39,15 @@ tests/cases/conformance/types/tuple/castingTuple.ts(31,1): error TS2304: Cannot // error var t3 = <[number, number]>numStrTuple; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2352: Neither type '[number, string]' nor type '[number, number]' is assignable to the other. -!!! error TS2352: Types of property '1' are incompatible. -!!! error TS2352: Type 'string' is not assignable to type 'number'. +!!! error TS2323: Type '[number, string]' is not comparable with type '[number, number]'. +!!! error TS2323: Types of property '1' are incompatible. +!!! error TS2323: Type 'string' is not comparable with type 'number'. var t9 = <[A, I]>classCDTuple; ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2352: Neither type '[C, D]' nor type '[A, I]' is assignable to the other. -!!! error TS2352: Types of property '0' are incompatible. -!!! error TS2352: Type 'C' is not assignable to type 'A'. -!!! error TS2352: Property 'a' is missing in type 'C'. +!!! error TS2323: Type '[C, D]' is not comparable with type '[A, I]'. +!!! error TS2323: Types of property '0' are incompatible. +!!! error TS2323: Type 'C' is not comparable with type 'A'. +!!! error TS2323: Property 'a' is missing in type 'C'. var array1 = numStrTuple; ~~~~~~ !!! error TS2403: Subsequent variable declarations must have the same type. Variable 'array1' must be of type '{}[]', but here has type 'number[]'. diff --git a/tests/baselines/reference/contextualTyping39.errors.txt b/tests/baselines/reference/contextualTyping39.errors.txt index e43624fbead..844f302cb59 100644 --- a/tests/baselines/reference/contextualTyping39.errors.txt +++ b/tests/baselines/reference/contextualTyping39.errors.txt @@ -1,9 +1,9 @@ -tests/cases/compiler/contextualTyping39.ts(1,11): error TS2352: Neither type '() => string' nor type '() => number' is assignable to the other. - Type 'string' is not assignable to type 'number'. +tests/cases/compiler/contextualTyping39.ts(1,11): error TS2323: Type '() => string' is not comparable with type '() => number'. + Type 'string' is not comparable with type 'number'. ==== tests/cases/compiler/contextualTyping39.ts (1 errors) ==== var foo = <{ (): number; }> function() { return "err"; }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2352: Neither type '() => string' nor type '() => number' is assignable to the other. -!!! error TS2352: Type 'string' is not assignable to type 'number'. \ No newline at end of file +!!! error TS2323: Type '() => string' is not comparable with type '() => number'. +!!! error TS2323: Type 'string' is not comparable with type 'number'. \ No newline at end of file diff --git a/tests/baselines/reference/contextualTyping41.errors.txt b/tests/baselines/reference/contextualTyping41.errors.txt index 1ed6da1b782..2f1ac620b7a 100644 --- a/tests/baselines/reference/contextualTyping41.errors.txt +++ b/tests/baselines/reference/contextualTyping41.errors.txt @@ -1,9 +1,9 @@ -tests/cases/compiler/contextualTyping41.ts(1,11): error TS2352: Neither type '() => string' nor type '{ (): number; (i: number): number; }' is assignable to the other. - Type 'string' is not assignable to type 'number'. +tests/cases/compiler/contextualTyping41.ts(1,11): error TS2323: Type '() => string' is not comparable with type '{ (): number; (i: number): number; }'. + Type 'string' is not comparable with type 'number'. ==== tests/cases/compiler/contextualTyping41.ts (1 errors) ==== var foo = <{():number; (i:number):number; }> (function(){return "err";}); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2352: Neither type '() => string' nor type '{ (): number; (i: number): number; }' is assignable to the other. -!!! error TS2352: Type 'string' is not assignable to type 'number'. \ No newline at end of file +!!! error TS2323: Type '() => string' is not comparable with type '{ (): number; (i: number): number; }'. +!!! error TS2323: Type 'string' is not comparable with type 'number'. \ No newline at end of file diff --git a/tests/baselines/reference/defaultArgsInFunctionExpressions.errors.txt b/tests/baselines/reference/defaultArgsInFunctionExpressions.errors.txt index 156fdcc4c7a..82851017207 100644 --- a/tests/baselines/reference/defaultArgsInFunctionExpressions.errors.txt +++ b/tests/baselines/reference/defaultArgsInFunctionExpressions.errors.txt @@ -2,9 +2,9 @@ tests/cases/compiler/defaultArgsInFunctionExpressions.ts(4,19): error TS2345: Ar tests/cases/compiler/defaultArgsInFunctionExpressions.ts(5,1): error TS2322: Type 'number' is not assignable to type 'string'. tests/cases/compiler/defaultArgsInFunctionExpressions.ts(8,20): error TS2322: Type 'number' is not assignable to type 'string'. tests/cases/compiler/defaultArgsInFunctionExpressions.ts(11,1): error TS2322: Type 'string' is not assignable to type 'number'. -tests/cases/compiler/defaultArgsInFunctionExpressions.ts(14,51): error TS2352: Neither type 'string' nor type 'number' is assignable to the other. +tests/cases/compiler/defaultArgsInFunctionExpressions.ts(14,51): error TS2323: Type 'string' is not comparable with type 'number'. tests/cases/compiler/defaultArgsInFunctionExpressions.ts(17,41): error TS2322: Type 'string' is not assignable to type 'number'. -tests/cases/compiler/defaultArgsInFunctionExpressions.ts(20,62): error TS2352: Neither type 'string' nor type 'number' is assignable to the other. +tests/cases/compiler/defaultArgsInFunctionExpressions.ts(20,62): error TS2323: Type 'string' is not comparable with type 'number'. tests/cases/compiler/defaultArgsInFunctionExpressions.ts(28,15): error TS2304: Cannot find name 'T'. @@ -32,7 +32,7 @@ tests/cases/compiler/defaultArgsInFunctionExpressions.ts(28,15): error TS2304: C // Contextually type the default arg with the type annotation var f3 = function (a: (s: string) => any = (s) => s) { }; ~~~~~~~~~ -!!! error TS2352: Neither type 'string' nor type 'number' is assignable to the other. +!!! error TS2323: Type 'string' is not comparable with type 'number'. // Type check using the function's contextual type var f4: (a: number) => void = function (a = "") { }; @@ -42,7 +42,7 @@ tests/cases/compiler/defaultArgsInFunctionExpressions.ts(28,15): error TS2304: C // Contextually type the default arg using the function's contextual type var f5: (a: (s: string) => any) => void = function (a = s => s) { }; ~~~~~~~~~ -!!! error TS2352: Neither type 'string' nor type 'number' is assignable to the other. +!!! error TS2323: Type 'string' is not comparable with type 'number'. // Instantiated module module T { } diff --git a/tests/baselines/reference/fuzzy.errors.txt b/tests/baselines/reference/fuzzy.errors.txt index 72ac4c816f9..f79bc817a10 100644 --- a/tests/baselines/reference/fuzzy.errors.txt +++ b/tests/baselines/reference/fuzzy.errors.txt @@ -4,7 +4,7 @@ tests/cases/compiler/fuzzy.ts(21,20): error TS2322: Type '{ anything: number; on Types of property 'oneI' are incompatible. Type 'this' is not assignable to type 'I'. Type 'C' is not assignable to type 'I'. -tests/cases/compiler/fuzzy.ts(25,20): error TS2352: Neither type '{ oneI: this; }' nor type 'R' is assignable to the other. +tests/cases/compiler/fuzzy.ts(25,20): error TS2323: Type '{ oneI: this; }' is not comparable with type 'R'. Property 'anything' is missing in type '{ oneI: this; }'. @@ -43,8 +43,8 @@ tests/cases/compiler/fuzzy.ts(25,20): error TS2352: Neither type '{ oneI: this; worksToo():R { return ({ oneI: this }); ~~~~~~~~~~~~~~~~~~~ -!!! error TS2352: Neither type '{ oneI: this; }' nor type 'R' is assignable to the other. -!!! error TS2352: Property 'anything' is missing in type '{ oneI: this; }'. +!!! error TS2323: Type '{ oneI: this; }' is not comparable with type 'R'. +!!! error TS2323: Property 'anything' is missing in type '{ oneI: this; }'. } } } diff --git a/tests/baselines/reference/genericTypeAssertions1.errors.txt b/tests/baselines/reference/genericTypeAssertions1.errors.txt index 5479c5f948e..1e4439ce2ae 100644 --- a/tests/baselines/reference/genericTypeAssertions1.errors.txt +++ b/tests/baselines/reference/genericTypeAssertions1.errors.txt @@ -2,8 +2,8 @@ tests/cases/compiler/genericTypeAssertions1.ts(3,5): error TS2322: Type 'A>' is not assignable to type 'A'. Type 'A' is not assignable to type 'number'. -tests/cases/compiler/genericTypeAssertions1.ts(4,21): error TS2352: Neither type 'A' nor type 'A>' is assignable to the other. - Type 'number' is not assignable to type 'A'. +tests/cases/compiler/genericTypeAssertions1.ts(4,21): error TS2323: Type 'A' is not comparable with type 'A>'. + Type 'number' is not comparable with type 'A'. ==== tests/cases/compiler/genericTypeAssertions1.ts (3 errors) ==== @@ -18,5 +18,5 @@ tests/cases/compiler/genericTypeAssertions1.ts(4,21): error TS2352: Neither type !!! error TS2322: Type 'A>' is not assignable to type 'A'. !!! error TS2322: Type 'A' is not assignable to type 'number'. ~~~~~~~~~~~~~~~~~ -!!! error TS2352: Neither type 'A' nor type 'A>' is assignable to the other. -!!! error TS2352: Type 'number' is not assignable to type 'A'. \ No newline at end of file +!!! error TS2323: Type 'A' is not comparable with type 'A>'. +!!! error TS2323: Type 'number' is not comparable with type 'A'. \ No newline at end of file diff --git a/tests/baselines/reference/genericTypeAssertions2.errors.txt b/tests/baselines/reference/genericTypeAssertions2.errors.txt index eda4c83646c..ce20955ec1a 100644 --- a/tests/baselines/reference/genericTypeAssertions2.errors.txt +++ b/tests/baselines/reference/genericTypeAssertions2.errors.txt @@ -5,7 +5,7 @@ tests/cases/compiler/genericTypeAssertions2.ts(10,5): error TS2322: Type 'B' is not assignable to type 'B'. Property 'bar' is missing in type 'A'. -tests/cases/compiler/genericTypeAssertions2.ts(13,21): error TS2352: Neither type 'undefined[]' nor type 'A' is assignable to the other. +tests/cases/compiler/genericTypeAssertions2.ts(13,21): error TS2323: Type 'undefined[]' is not comparable with type 'A'. Property 'foo' is missing in type 'undefined[]'. @@ -33,5 +33,5 @@ tests/cases/compiler/genericTypeAssertions2.ts(13,21): error TS2352: Neither typ var r4: A = >new A(); var r5: A = >[]; // error ~~~~~~~~~~~~~ -!!! error TS2352: Neither type 'undefined[]' nor type 'A' is assignable to the other. -!!! error TS2352: Property 'foo' is missing in type 'undefined[]'. \ No newline at end of file +!!! error TS2323: Type 'undefined[]' is not comparable with type 'A'. +!!! error TS2323: Property 'foo' is missing in type 'undefined[]'. \ No newline at end of file diff --git a/tests/baselines/reference/genericTypeAssertions4.errors.txt b/tests/baselines/reference/genericTypeAssertions4.errors.txt index 055de774b39..3456b233f67 100644 --- a/tests/baselines/reference/genericTypeAssertions4.errors.txt +++ b/tests/baselines/reference/genericTypeAssertions4.errors.txt @@ -1,8 +1,8 @@ tests/cases/compiler/genericTypeAssertions4.ts(19,5): error TS2322: Type 'A' is not assignable to type 'T'. tests/cases/compiler/genericTypeAssertions4.ts(20,5): error TS2322: Type 'B' is not assignable to type 'T'. tests/cases/compiler/genericTypeAssertions4.ts(21,5): error TS2322: Type 'C' is not assignable to type 'T'. -tests/cases/compiler/genericTypeAssertions4.ts(23,9): error TS2352: Neither type 'B' nor type 'T' is assignable to the other. -tests/cases/compiler/genericTypeAssertions4.ts(24,9): error TS2352: Neither type 'C' nor type 'T' is assignable to the other. +tests/cases/compiler/genericTypeAssertions4.ts(23,9): error TS2323: Type 'B' is not comparable with type 'T'. +tests/cases/compiler/genericTypeAssertions4.ts(24,9): error TS2323: Type 'C' is not comparable with type 'T'. ==== tests/cases/compiler/genericTypeAssertions4.ts (5 errors) ==== @@ -36,8 +36,8 @@ tests/cases/compiler/genericTypeAssertions4.ts(24,9): error TS2352: Neither type y = a; y = b; // error: cannot convert B to T ~~~~ -!!! error TS2352: Neither type 'B' nor type 'T' is assignable to the other. +!!! error TS2323: Type 'B' is not comparable with type 'T'. y = c; // error: cannot convert C to T ~~~~ -!!! error TS2352: Neither type 'C' nor type 'T' is assignable to the other. +!!! error TS2323: Type 'C' is not comparable with type 'T'. } \ No newline at end of file diff --git a/tests/baselines/reference/genericTypeAssertions5.errors.txt b/tests/baselines/reference/genericTypeAssertions5.errors.txt index e315a7f122a..b621decb062 100644 --- a/tests/baselines/reference/genericTypeAssertions5.errors.txt +++ b/tests/baselines/reference/genericTypeAssertions5.errors.txt @@ -1,8 +1,8 @@ tests/cases/compiler/genericTypeAssertions5.ts(19,5): error TS2322: Type 'A' is not assignable to type 'T'. tests/cases/compiler/genericTypeAssertions5.ts(20,5): error TS2322: Type 'B' is not assignable to type 'T'. tests/cases/compiler/genericTypeAssertions5.ts(21,5): error TS2322: Type 'C' is not assignable to type 'T'. -tests/cases/compiler/genericTypeAssertions5.ts(23,9): error TS2352: Neither type 'B' nor type 'T' is assignable to the other. -tests/cases/compiler/genericTypeAssertions5.ts(24,9): error TS2352: Neither type 'C' nor type 'T' is assignable to the other. +tests/cases/compiler/genericTypeAssertions5.ts(23,9): error TS2323: Type 'B' is not comparable with type 'T'. +tests/cases/compiler/genericTypeAssertions5.ts(24,9): error TS2323: Type 'C' is not comparable with type 'T'. ==== tests/cases/compiler/genericTypeAssertions5.ts (5 errors) ==== @@ -36,8 +36,8 @@ tests/cases/compiler/genericTypeAssertions5.ts(24,9): error TS2352: Neither type y = a; y = b; // error: cannot convert B to T ~~~~ -!!! error TS2352: Neither type 'B' nor type 'T' is assignable to the other. +!!! error TS2323: Type 'B' is not comparable with type 'T'. y = c; // error: cannot convert C to T ~~~~ -!!! error TS2352: Neither type 'C' nor type 'T' is assignable to the other. +!!! error TS2323: Type 'C' is not comparable with type 'T'. } \ No newline at end of file diff --git a/tests/baselines/reference/genericTypeAssertions6.errors.txt b/tests/baselines/reference/genericTypeAssertions6.errors.txt index 29ca99ecb1a..3637a5cbb5b 100644 --- a/tests/baselines/reference/genericTypeAssertions6.errors.txt +++ b/tests/baselines/reference/genericTypeAssertions6.errors.txt @@ -1,7 +1,7 @@ -tests/cases/compiler/genericTypeAssertions6.ts(8,13): error TS2352: Neither type 'U' nor type 'T' is assignable to the other. -tests/cases/compiler/genericTypeAssertions6.ts(9,13): error TS2352: Neither type 'T' nor type 'U' is assignable to the other. -tests/cases/compiler/genericTypeAssertions6.ts(19,17): error TS2352: Neither type 'U' nor type 'T' is assignable to the other. - Type 'Date' is not assignable to type 'T'. +tests/cases/compiler/genericTypeAssertions6.ts(8,13): error TS2323: Type 'U' is not comparable with type 'T'. +tests/cases/compiler/genericTypeAssertions6.ts(9,13): error TS2323: Type 'T' is not comparable with type 'U'. +tests/cases/compiler/genericTypeAssertions6.ts(19,17): error TS2323: Type 'U' is not comparable with type 'T'. + Type 'Date' is not comparable with type 'T'. ==== tests/cases/compiler/genericTypeAssertions6.ts (3 errors) ==== @@ -14,10 +14,10 @@ tests/cases/compiler/genericTypeAssertions6.ts(19,17): error TS2352: Neither typ f(x: T, y: U) { x = y; ~~~~ -!!! error TS2352: Neither type 'U' nor type 'T' is assignable to the other. +!!! error TS2323: Type 'U' is not comparable with type 'T'. y = x; ~~~~ -!!! error TS2352: Neither type 'T' nor type 'U' is assignable to the other. +!!! error TS2323: Type 'T' is not comparable with type 'U'. } } @@ -29,8 +29,8 @@ tests/cases/compiler/genericTypeAssertions6.ts(19,17): error TS2352: Neither typ var d = new Date(); var e = new Date(); ~~~~~~~~~~~~~~~~ -!!! error TS2352: Neither type 'U' nor type 'T' is assignable to the other. -!!! error TS2352: Type 'Date' is not assignable to type 'T'. +!!! error TS2323: Type 'U' is not comparable with type 'T'. +!!! error TS2323: Type 'Date' is not comparable with type 'T'. } } diff --git a/tests/baselines/reference/intTypeCheck.errors.txt b/tests/baselines/reference/intTypeCheck.errors.txt index e48d1b1dc73..defcc276844 100644 --- a/tests/baselines/reference/intTypeCheck.errors.txt +++ b/tests/baselines/reference/intTypeCheck.errors.txt @@ -61,7 +61,7 @@ tests/cases/compiler/intTypeCheck.ts(176,22): error TS2304: Cannot find name 'i6 tests/cases/compiler/intTypeCheck.ts(177,17): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. tests/cases/compiler/intTypeCheck.ts(182,5): error TS2322: Type '{}' is not assignable to type 'i7'. tests/cases/compiler/intTypeCheck.ts(183,5): error TS2322: Type 'Object' is not assignable to type 'i7'. -tests/cases/compiler/intTypeCheck.ts(185,17): error TS2352: Neither type 'Base' nor type 'i7' is assignable to the other. +tests/cases/compiler/intTypeCheck.ts(185,17): error TS2323: Type 'Base' is not comparable with type 'i7'. tests/cases/compiler/intTypeCheck.ts(187,5): error TS2322: Type '() => void' is not assignable to type 'i7'. tests/cases/compiler/intTypeCheck.ts(190,5): error TS2322: Type 'boolean' is not assignable to type 'i7'. tests/cases/compiler/intTypeCheck.ts(190,21): error TS1109: Expression expected. @@ -377,7 +377,7 @@ tests/cases/compiler/intTypeCheck.ts(205,17): error TS2351: Cannot use 'new' wit var obj69: i7 = new obj66; var obj70: i7 = new Base; ~~~~~~~~~~~~ -!!! error TS2352: Neither type 'Base' nor type 'i7' is assignable to the other. +!!! error TS2323: Type 'Base' is not comparable with type 'i7'. var obj71: i7 = null; var obj72: i7 = function () { }; ~~~~~ diff --git a/tests/baselines/reference/literals-negative.errors.txt b/tests/baselines/reference/literals-negative.errors.txt index d783e5dfa02..f2a56614cbc 100644 --- a/tests/baselines/reference/literals-negative.errors.txt +++ b/tests/baselines/reference/literals-negative.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/literals-negative.ts(5,9): error TS2352: Neither type 'number' nor type 'boolean' is assignable to the other. +tests/cases/compiler/literals-negative.ts(5,9): error TS2323: Type 'number' is not comparable with type 'boolean'. ==== tests/cases/compiler/literals-negative.ts (1 errors) ==== @@ -8,7 +8,7 @@ tests/cases/compiler/literals-negative.ts(5,9): error TS2352: Neither type 'numb var s = (null); var b = (n); ~~~~~~~~~~~~ -!!! error TS2352: Neither type 'number' nor type 'boolean' is assignable to the other. +!!! error TS2323: Type 'number' is not comparable with type 'boolean'. function isVoid() : void { } diff --git a/tests/baselines/reference/noImplicitAnyInCastExpression.errors.txt b/tests/baselines/reference/noImplicitAnyInCastExpression.errors.txt index 66a7773ab49..333a940cc37 100644 --- a/tests/baselines/reference/noImplicitAnyInCastExpression.errors.txt +++ b/tests/baselines/reference/noImplicitAnyInCastExpression.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/noImplicitAnyInCastExpression.ts(16,2): error TS2352: Neither type '{ c: null; }' nor type 'IFoo' is assignable to the other. +tests/cases/compiler/noImplicitAnyInCastExpression.ts(16,2): error TS2323: Type '{ c: null; }' is not comparable with type 'IFoo'. Property 'a' is missing in type '{ c: null; }'. @@ -20,5 +20,5 @@ tests/cases/compiler/noImplicitAnyInCastExpression.ts(16,2): error TS2352: Neith // Neither types is assignable to each other ({ c: null }); ~~~~~~~~~~~~~~~~~ -!!! error TS2352: Neither type '{ c: null; }' nor type 'IFoo' is assignable to the other. -!!! error TS2352: Property 'a' is missing in type '{ c: null; }'. \ No newline at end of file +!!! error TS2323: Type '{ c: null; }' is not comparable with type 'IFoo'. +!!! error TS2323: Property 'a' is missing in type '{ c: null; }'. \ No newline at end of file diff --git a/tests/baselines/reference/objectTypesIdentityWithPrivates3.errors.txt b/tests/baselines/reference/objectTypesIdentityWithPrivates3.errors.txt index 9cbaa730022..6bd4dfd0544 100644 --- a/tests/baselines/reference/objectTypesIdentityWithPrivates3.errors.txt +++ b/tests/baselines/reference/objectTypesIdentityWithPrivates3.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/types/typeRelationships/typeAndMemberIdentity/objectTypesIdentityWithPrivates3.ts(25,1): error TS2352: Neither type 'C3' nor type 'C4' is assignable to the other. +tests/cases/conformance/types/typeRelationships/typeAndMemberIdentity/objectTypesIdentityWithPrivates3.ts(25,1): error TS2323: Type 'C3' is not comparable with type 'C4'. Property 'y' is missing in type 'C3'. @@ -29,5 +29,5 @@ tests/cases/conformance/types/typeRelationships/typeAndMemberIdentity/objectType var c3: C3; c3; // Should fail (private x originates in the same declaration, but different types) ~~~~~~ -!!! error TS2352: Neither type 'C3' nor type 'C4' is assignable to the other. -!!! error TS2352: Property 'y' is missing in type 'C3'. \ No newline at end of file +!!! error TS2323: Type 'C3' is not comparable with type 'C4'. +!!! error TS2323: Property 'y' is missing in type 'C3'. \ No newline at end of file diff --git a/tests/baselines/reference/switchAssignmentCompat.errors.txt b/tests/baselines/reference/switchAssignmentCompat.errors.txt index 6a2755365ab..cdfcc423f03 100644 --- a/tests/baselines/reference/switchAssignmentCompat.errors.txt +++ b/tests/baselines/reference/switchAssignmentCompat.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/switchAssignmentCompat.ts(4,10): error TS2322: Type 'typeof Foo' is not assignable to type 'number'. +tests/cases/compiler/switchAssignmentCompat.ts(4,10): error TS2323: Type 'typeof Foo' is not comparable with type 'number'. ==== tests/cases/compiler/switchAssignmentCompat.ts (1 errors) ==== @@ -7,6 +7,6 @@ tests/cases/compiler/switchAssignmentCompat.ts(4,10): error TS2322: Type 'typeof switch (0) { case Foo: break; // Error expected ~~~ -!!! error TS2322: Type 'typeof Foo' is not assignable to type 'number'. +!!! error TS2323: Type 'typeof Foo' is not comparable with type 'number'. } \ No newline at end of file diff --git a/tests/baselines/reference/switchCaseWithIntersectionTypes01.errors.txt b/tests/baselines/reference/switchCaseWithIntersectionTypes01.errors.txt index 967a59071af..417d4394bd8 100644 --- a/tests/baselines/reference/switchCaseWithIntersectionTypes01.errors.txt +++ b/tests/baselines/reference/switchCaseWithIntersectionTypes01.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithIntersectionTypes01.ts(19,10): error TS2322: Type 'number & boolean' is not assignable to type 'string & number'. - Type 'number & boolean' is not assignable to type 'string'. - Type 'boolean' is not assignable to type 'string'. -tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithIntersectionTypes01.ts(23,10): error TS2322: Type 'boolean' is not assignable to type 'string & number'. - Type 'boolean' is not assignable to type 'string'. +tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithIntersectionTypes01.ts(19,10): error TS2323: Type 'number & boolean' is not comparable with type 'string & number'. + Type 'number & boolean' is not comparable with type 'string'. + Type 'boolean' is not comparable with type 'string'. +tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithIntersectionTypes01.ts(23,10): error TS2323: Type 'boolean' is not comparable with type 'string & number'. + Type 'boolean' is not comparable with type 'string'. ==== tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithIntersectionTypes01.ts (2 errors) ==== @@ -26,15 +26,15 @@ tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithInterse // Overlap in constituents case numAndBool: ~~~~~~~~~~ -!!! error TS2322: Type 'number & boolean' is not assignable to type 'string & number'. -!!! error TS2322: Type 'number & boolean' is not assignable to type 'string'. -!!! error TS2322: Type 'boolean' is not assignable to type 'string'. +!!! error TS2323: Type 'number & boolean' is not comparable with type 'string & number'. +!!! error TS2323: Type 'number & boolean' is not comparable with type 'string'. +!!! error TS2323: Type 'boolean' is not comparable with type 'string'. break; // No relation case bool: ~~~~ -!!! error TS2322: Type 'boolean' is not assignable to type 'string & number'. -!!! error TS2322: Type 'boolean' is not assignable to type 'string'. +!!! error TS2323: Type 'boolean' is not comparable with type 'string & number'. +!!! error TS2323: Type 'boolean' is not comparable with type 'string'. break; } \ No newline at end of file diff --git a/tests/baselines/reference/switchCaseWithUnionTypes01.errors.txt b/tests/baselines/reference/switchCaseWithUnionTypes01.errors.txt index 66f01cc1d34..3fbcb4c4658 100644 --- a/tests/baselines/reference/switchCaseWithUnionTypes01.errors.txt +++ b/tests/baselines/reference/switchCaseWithUnionTypes01.errors.txt @@ -1,5 +1,5 @@ -tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithUnionTypes01.ts(23,10): error TS2322: Type 'boolean' is not assignable to type 'string | number'. - Type 'boolean' is not assignable to type 'number'. +tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithUnionTypes01.ts(23,10): error TS2323: Type 'boolean' is not comparable with type 'string | number'. + Type 'boolean' is not comparable with type 'number'. ==== tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithUnionTypes01.ts (1 errors) ==== @@ -27,7 +27,7 @@ tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithUnionTy // No relation case bool: ~~~~ -!!! error TS2322: Type 'boolean' is not assignable to type 'string | number'. -!!! error TS2322: Type 'boolean' is not assignable to type 'number'. +!!! error TS2323: Type 'boolean' is not comparable with type 'string | number'. +!!! error TS2323: Type 'boolean' is not comparable with type 'number'. break; } \ No newline at end of file diff --git a/tests/baselines/reference/switchCasesExpressionTypeMismatch.errors.txt b/tests/baselines/reference/switchCasesExpressionTypeMismatch.errors.txt index de739af007d..c3009179995 100644 --- a/tests/baselines/reference/switchCasesExpressionTypeMismatch.errors.txt +++ b/tests/baselines/reference/switchCasesExpressionTypeMismatch.errors.txt @@ -1,6 +1,6 @@ -tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(4,10): error TS2322: Type 'typeof Foo' is not assignable to type 'number'. -tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(5,10): error TS2322: Type 'string' is not assignable to type 'number'. -tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(7,10): error TS2322: Type 'boolean' is not assignable to type 'number'. +tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(4,10): error TS2323: Type 'typeof Foo' is not comparable with type 'number'. +tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(5,10): error TS2323: Type 'string' is not comparable with type 'number'. +tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(7,10): error TS2323: Type 'boolean' is not comparable with type 'number'. ==== tests/cases/compiler/switchCasesExpressionTypeMismatch.ts (3 errors) ==== @@ -9,14 +9,14 @@ tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(7,10): error TS2322: T switch (0) { case Foo: break; // Error ~~~ -!!! error TS2322: Type 'typeof Foo' is not assignable to type 'number'. +!!! error TS2323: Type 'typeof Foo' is not comparable with type 'number'. case "sss": break; // Error ~~~~~ -!!! error TS2322: Type 'string' is not assignable to type 'number'. +!!! error TS2323: Type 'string' is not comparable with type 'number'. case 123: break; // No Error case true: break; // Error ~~~~ -!!! error TS2322: Type 'boolean' is not assignable to type 'number'. +!!! error TS2323: Type 'boolean' is not comparable with type 'number'. } var s: any = 0; diff --git a/tests/baselines/reference/switchStatements.errors.txt b/tests/baselines/reference/switchStatements.errors.txt index c99b0eba909..eddc9eaa833 100644 --- a/tests/baselines/reference/switchStatements.errors.txt +++ b/tests/baselines/reference/switchStatements.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/statements/switchStatements/switchStatements.ts(35,20): error TS2322: Type '{ id: number; name: string; }' is not assignable to type 'C'. +tests/cases/conformance/statements/switchStatements/switchStatements.ts(35,20): error TS2323: Type '{ id: number; name: string; }' is not comparable with type 'C'. Object literal may only specify known properties, and 'name' does not exist in type 'C'. @@ -39,8 +39,8 @@ tests/cases/conformance/statements/switchStatements/switchStatements.ts(35,20): case new D(): case { id: 12, name: '' }: ~~~~~~~~ -!!! error TS2322: Type '{ id: number; name: string; }' is not assignable to type 'C'. -!!! error TS2322: Object literal may only specify known properties, and 'name' does not exist in type 'C'. +!!! error TS2323: Type '{ id: number; name: string; }' is not comparable with type 'C'. +!!! error TS2323: Object literal may only specify known properties, and 'name' does not exist in type 'C'. case new C(): } diff --git a/tests/baselines/reference/typeAssertions.errors.txt b/tests/baselines/reference/typeAssertions.errors.txt index a2ad28801c8..1e9e45171f6 100644 --- a/tests/baselines/reference/typeAssertions.errors.txt +++ b/tests/baselines/reference/typeAssertions.errors.txt @@ -1,11 +1,11 @@ tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(5,5): error TS2346: Supplied parameters do not match any signature of call target. -tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(31,12): error TS2352: Neither type 'SomeOther' nor type 'SomeBase' is assignable to the other. +tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(31,12): error TS2323: Type 'SomeOther' is not comparable with type 'SomeBase'. Property 'p' is missing in type 'SomeOther'. -tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(35,15): error TS2352: Neither type 'SomeOther' nor type 'SomeDerived' is assignable to the other. +tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(35,15): error TS2323: Type 'SomeOther' is not comparable with type 'SomeDerived'. Property 'x' is missing in type 'SomeOther'. -tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(37,13): error TS2352: Neither type 'SomeDerived' nor type 'SomeOther' is assignable to the other. +tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(37,13): error TS2323: Type 'SomeDerived' is not comparable with type 'SomeOther'. Property 'q' is missing in type 'SomeDerived'. -tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(38,13): error TS2352: Neither type 'SomeBase' nor type 'SomeOther' is assignable to the other. +tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(38,13): error TS2323: Type 'SomeBase' is not comparable with type 'SomeOther'. Property 'q' is missing in type 'SomeBase'. @@ -44,24 +44,24 @@ tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(38,13): err someBase = someBase; someBase = someOther; // Error ~~~~~~~~~~~~~~~~~~~ -!!! error TS2352: Neither type 'SomeOther' nor type 'SomeBase' is assignable to the other. -!!! error TS2352: Property 'p' is missing in type 'SomeOther'. +!!! error TS2323: Type 'SomeOther' is not comparable with type 'SomeBase'. +!!! error TS2323: Property 'p' is missing in type 'SomeOther'. someDerived = someDerived; someDerived = someBase; someDerived = someOther; // Error ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2352: Neither type 'SomeOther' nor type 'SomeDerived' is assignable to the other. -!!! error TS2352: Property 'x' is missing in type 'SomeOther'. +!!! error TS2323: Type 'SomeOther' is not comparable with type 'SomeDerived'. +!!! error TS2323: Property 'x' is missing in type 'SomeOther'. someOther = someDerived; // Error ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2352: Neither type 'SomeDerived' nor type 'SomeOther' is assignable to the other. -!!! error TS2352: Property 'q' is missing in type 'SomeDerived'. +!!! error TS2323: Type 'SomeDerived' is not comparable with type 'SomeOther'. +!!! error TS2323: Property 'q' is missing in type 'SomeDerived'. someOther = someBase; // Error ~~~~~~~~~~~~~~~~~~~ -!!! error TS2352: Neither type 'SomeBase' nor type 'SomeOther' is assignable to the other. -!!! error TS2352: Property 'q' is missing in type 'SomeBase'. +!!! error TS2323: Type 'SomeBase' is not comparable with type 'SomeOther'. +!!! error TS2323: Property 'q' is missing in type 'SomeBase'. someOther = someOther; diff --git a/tests/baselines/reference/typeAssertionsWithIntersectionTypes01.errors.txt b/tests/baselines/reference/typeAssertionsWithIntersectionTypes01.errors.txt index 162e55a225e..1b0cd98533d 100644 --- a/tests/baselines/reference/typeAssertionsWithIntersectionTypes01.errors.txt +++ b/tests/baselines/reference/typeAssertionsWithIntersectionTypes01.errors.txt @@ -1,7 +1,7 @@ -tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithIntersectionTypes01.ts(17,9): error TS2352: Neither type 'I2' nor type 'I1 & I3' is assignable to the other. - Type 'I2' is not assignable to type 'I3'. +tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithIntersectionTypes01.ts(17,9): error TS2323: Type 'I2' is not comparable with type 'I1 & I3'. + Type 'I2' is not comparable with type 'I3'. Property 'p3' is missing in type 'I2'. -tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithIntersectionTypes01.ts(18,9): error TS2352: Neither type 'I2' nor type 'I3' is assignable to the other. +tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithIntersectionTypes01.ts(18,9): error TS2323: Type 'I2' is not comparable with type 'I3'. ==== tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithIntersectionTypes01.ts (2 errors) ==== @@ -23,12 +23,12 @@ tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithInt var a = z; ~~~~~~~~~~ -!!! error TS2352: Neither type 'I2' nor type 'I1 & I3' is assignable to the other. -!!! error TS2352: Type 'I2' is not assignable to type 'I3'. -!!! error TS2352: Property 'p3' is missing in type 'I2'. +!!! error TS2323: Type 'I2' is not comparable with type 'I1 & I3'. +!!! error TS2323: Type 'I2' is not comparable with type 'I3'. +!!! error TS2323: Property 'p3' is missing in type 'I2'. var b = z; ~~~~~ -!!! error TS2352: Neither type 'I2' nor type 'I3' is assignable to the other. +!!! error TS2323: Type 'I2' is not comparable with type 'I3'. var c = z; var d = y; \ No newline at end of file diff --git a/tests/baselines/reference/typeAssertionsWithUnionTypes01.errors.txt b/tests/baselines/reference/typeAssertionsWithUnionTypes01.errors.txt index 68ab174ff98..21d1bccdd5d 100644 --- a/tests/baselines/reference/typeAssertionsWithUnionTypes01.errors.txt +++ b/tests/baselines/reference/typeAssertionsWithUnionTypes01.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithUnionTypes01.ts(14,9): error TS2352: Neither type 'I1' nor type 'number' is assignable to the other. +tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithUnionTypes01.ts(14,9): error TS2323: Type 'I1' is not comparable with type 'number'. ==== tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithUnionTypes01.ts (1 errors) ==== @@ -17,7 +17,7 @@ tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithUni var a = z; var b = z; ~~~~~~~~~ -!!! error TS2352: Neither type 'I1' nor type 'number' is assignable to the other. +!!! error TS2323: Type 'I1' is not comparable with type 'number'. var c = z; var d = y; \ No newline at end of file From 80a50aa104054df7846d244bfbc5ed1ecfa408ac Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 3 Nov 2015 17:39:53 -0800 Subject: [PATCH 016/274] Appease the almighty linter. --- src/compiler/checker.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a804cacb7de..9d069a547d9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4832,13 +4832,13 @@ namespace ts { sourceType = typeToString(source, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType); targetType = typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType); } - + if (!message) { message = relation === comparableRelation ? Diagnostics.Type_0_is_not_comparable_with_type_1 : - Diagnostics.Type_0_is_not_assignable_to_type_1 + Diagnostics.Type_0_is_not_assignable_to_type_1; } - + reportError(message, sourceType, targetType); } From 42c49cea0d1b393ab57bf748ae1c3bb42e00ca57 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 4 Nov 2015 13:05:46 -0800 Subject: [PATCH 017/274] Style. --- src/compiler/checker.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9d069a547d9..f16722b7c57 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4882,13 +4882,13 @@ namespace ts { let saveErrorInfo = errorInfo; - // Note that the "each" checks must precede the "some" checks to produce the correct results + // Note that these checks are specifically ordered to produce correct results. if (source.flags & TypeFlags.Union) { if (relation === comparableRelation) { result = someTypeRelatedToType(source as UnionType, target, reportErrors); } else { - result = eachTypeRelatedToType(source, target, reportErrors); + result = eachTypeRelatedToType(source as UnionType, target, reportErrors); } if (result) { @@ -4896,25 +4896,25 @@ namespace ts { } } else if (target.flags & TypeFlags.Intersection) { - result = typeRelatedToEachType(source, target, reportErrors); + result = typeRelatedToEachType(source, target as IntersectionType, reportErrors); if (result) { return result; } } else { - // It is necessary to try "some" checks on both sides because there may be nested "each" checks + // It is necessary to try these "some" checks on both sides because there may be nested "each" checks // on either side that need to be prioritized. For example, A | B = (A | B) & (C | D) or // A & B = (A & B) | (C & D). if (source.flags & TypeFlags.Intersection) { // If target is a union type then the check following this one will report errors, // so we'll suppress any errors we could run into here. - if (result = someTypeRelatedToType(source, target, reportErrors && !(target.flags & TypeFlags.Union))) { + if (result = someTypeRelatedToType(source as IntersectionType, target, reportErrors && !(target.flags & TypeFlags.Union))) { return result; } } if (target.flags & TypeFlags.Union) { - if (result = typeRelatedToSomeType(source, target, reportErrors)) { + if (result = typeRelatedToSomeType(source, target as UnionType, reportErrors)) { return result; } } @@ -12727,6 +12727,7 @@ namespace ts { let caseClause = clause; // TypeScript 1.0 spec (April 2014): 5.9 // In a 'switch' statement, each 'case' expression must be of a type that is assignable to or from the type of the 'switch' expression. + // TODO (drosen): this needs to be amended to reflect the "comparable" relationship. let caseType = checkExpression(caseClause.expression); if (!isTypeComparableTo(expressionType, caseType)) { From 6c8c1223f29bbd657cb042fef80f0fa0ccf39226 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 4 Nov 2015 13:19:15 -0800 Subject: [PATCH 018/274] 'with' to 'to' --- src/compiler/checker.ts | 2 +- src/compiler/diagnosticMessages.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f16722b7c57..1d859cee660 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4835,7 +4835,7 @@ namespace ts { if (!message) { message = relation === comparableRelation ? - Diagnostics.Type_0_is_not_comparable_with_type_1 : + Diagnostics.Type_0_is_not_comparable_to_type_1 : Diagnostics.Type_0_is_not_assignable_to_type_1; } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 4f1b4869918..c295a828175 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -888,7 +888,7 @@ "category": "Error", "code": 2322 }, - "Type '{0}' is not comparable with type '{1}'.": { + "Type '{0}' is not comparable to type '{1}'.": { "category": "Error", "code": 2323 }, From f6eacb9606bd983e91d18719d4b06a357c7fa837 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 4 Nov 2015 13:19:56 -0800 Subject: [PATCH 019/274] Accepted baselines. --- .../baselines/reference/arrayCast.errors.txt | 8 ++++---- .../reference/asOperator2.errors.txt | 4 ++-- .../asOperatorContextualType.errors.txt | 8 ++++---- .../reference/asOperatorNames.errors.txt | 4 ++-- .../reference/castingTuple.errors.txt | 16 +++++++-------- .../reference/contextualTyping39.errors.txt | 8 ++++---- .../reference/contextualTyping41.errors.txt | 8 ++++---- ...efaultArgsInFunctionExpressions.errors.txt | 8 ++++---- tests/baselines/reference/fuzzy.errors.txt | 4 ++-- .../genericTypeAssertions1.errors.txt | 8 ++++---- .../genericTypeAssertions2.errors.txt | 4 ++-- .../genericTypeAssertions4.errors.txt | 8 ++++---- .../genericTypeAssertions5.errors.txt | 8 ++++---- .../genericTypeAssertions6.errors.txt | 16 +++++++-------- .../reference/intTypeCheck.errors.txt | 4 ++-- .../reference/literals-negative.errors.txt | 4 ++-- .../noImplicitAnyInCastExpression.errors.txt | 4 ++-- ...bjectTypesIdentityWithPrivates3.errors.txt | 4 ++-- .../switchAssignmentCompat.errors.txt | 4 ++-- ...itchCaseWithIntersectionTypes01.errors.txt | 20 +++++++++---------- .../switchCaseWithUnionTypes01.errors.txt | 8 ++++---- ...itchCasesExpressionTypeMismatch.errors.txt | 12 +++++------ .../reference/switchStatements.errors.txt | 4 ++-- .../reference/typeAssertions.errors.txt | 16 +++++++-------- ...sertionsWithIntersectionTypes01.errors.txt | 12 +++++------ .../typeAssertionsWithUnionTypes01.errors.txt | 4 ++-- 26 files changed, 104 insertions(+), 104 deletions(-) diff --git a/tests/baselines/reference/arrayCast.errors.txt b/tests/baselines/reference/arrayCast.errors.txt index c73f3ce879c..bb895475a18 100644 --- a/tests/baselines/reference/arrayCast.errors.txt +++ b/tests/baselines/reference/arrayCast.errors.txt @@ -1,5 +1,5 @@ -tests/cases/compiler/arrayCast.ts(3,23): error TS2323: Type '{ foo: string; }[]' is not comparable with type '{ id: number; }[]'. - Type '{ foo: string; }' is not comparable with type '{ id: number; }'. +tests/cases/compiler/arrayCast.ts(3,23): error TS2323: Type '{ foo: string; }[]' is not comparable to type '{ id: number; }[]'. + Type '{ foo: string; }' is not comparable to type '{ id: number; }'. Object literal may only specify known properties, and 'foo' does not exist in type '{ id: number; }'. @@ -8,8 +8,8 @@ tests/cases/compiler/arrayCast.ts(3,23): error TS2323: Type '{ foo: string; }[]' // has type { foo: string }[], which is not assignable to { id: number }[]. <{ id: number; }[]>[{ foo: "s" }]; ~~~~~~~~ -!!! error TS2323: Type '{ foo: string; }[]' is not comparable with type '{ id: number; }[]'. -!!! error TS2323: Type '{ foo: string; }' is not comparable with type '{ id: number; }'. +!!! error TS2323: Type '{ foo: string; }[]' is not comparable to type '{ id: number; }[]'. +!!! error TS2323: Type '{ foo: string; }' is not comparable to type '{ id: number; }'. !!! error TS2323: Object literal may only specify known properties, and 'foo' does not exist in type '{ id: number; }'. // Should succeed, as the {} element causes the type of the array to be {}[] diff --git a/tests/baselines/reference/asOperator2.errors.txt b/tests/baselines/reference/asOperator2.errors.txt index d3eb568d79a..0930191aae1 100644 --- a/tests/baselines/reference/asOperator2.errors.txt +++ b/tests/baselines/reference/asOperator2.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/expressions/asOperator/asOperator2.ts(1,9): error TS2323: Type 'number' is not comparable with type 'string'. +tests/cases/conformance/expressions/asOperator/asOperator2.ts(1,9): error TS2323: Type 'number' is not comparable to type 'string'. ==== tests/cases/conformance/expressions/asOperator/asOperator2.ts (1 errors) ==== var x = 23 as string; ~~~~~~~~~~~~ -!!! error TS2323: Type 'number' is not comparable with type 'string'. +!!! error TS2323: Type 'number' is not comparable to type 'string'. \ No newline at end of file diff --git a/tests/baselines/reference/asOperatorContextualType.errors.txt b/tests/baselines/reference/asOperatorContextualType.errors.txt index a2ea2a7f83e..1a6cf43827c 100644 --- a/tests/baselines/reference/asOperatorContextualType.errors.txt +++ b/tests/baselines/reference/asOperatorContextualType.errors.txt @@ -1,10 +1,10 @@ -tests/cases/conformance/expressions/asOperator/asOperatorContextualType.ts(2,9): error TS2323: Type '(v: number) => number' is not comparable with type '(x: number) => string'. - Type 'number' is not comparable with type 'string'. +tests/cases/conformance/expressions/asOperator/asOperatorContextualType.ts(2,9): error TS2323: Type '(v: number) => number' is not comparable to type '(x: number) => string'. + Type 'number' is not comparable to type 'string'. ==== tests/cases/conformance/expressions/asOperator/asOperatorContextualType.ts (1 errors) ==== // should error var x = (v => v) as (x: number) => string; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2323: Type '(v: number) => number' is not comparable with type '(x: number) => string'. -!!! error TS2323: Type 'number' is not comparable with type 'string'. \ No newline at end of file +!!! error TS2323: Type '(v: number) => number' is not comparable to type '(x: number) => string'. +!!! error TS2323: Type 'number' is not comparable to type 'string'. \ No newline at end of file diff --git a/tests/baselines/reference/asOperatorNames.errors.txt b/tests/baselines/reference/asOperatorNames.errors.txt index 61847f5dba1..f4ef8a64e2b 100644 --- a/tests/baselines/reference/asOperatorNames.errors.txt +++ b/tests/baselines/reference/asOperatorNames.errors.txt @@ -1,11 +1,11 @@ -tests/cases/conformance/expressions/asOperator/asOperatorNames.ts(2,9): error TS2323: Type 'number' is not comparable with type 'string'. +tests/cases/conformance/expressions/asOperator/asOperatorNames.ts(2,9): error TS2323: Type 'number' is not comparable to type 'string'. ==== tests/cases/conformance/expressions/asOperator/asOperatorNames.ts (1 errors) ==== var a = 20; var b = a as string; ~~~~~~~~~~~ -!!! error TS2323: Type 'number' is not comparable with type 'string'. +!!! error TS2323: Type 'number' is not comparable to type 'string'. var as = "hello"; var as1 = as as string; \ No newline at end of file diff --git a/tests/baselines/reference/castingTuple.errors.txt b/tests/baselines/reference/castingTuple.errors.txt index 04caf8e22c5..4430c932bfc 100644 --- a/tests/baselines/reference/castingTuple.errors.txt +++ b/tests/baselines/reference/castingTuple.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/types/tuple/castingTuple.ts(28,10): error TS2323: Type '[number, string]' is not comparable with type '[number, number]'. +tests/cases/conformance/types/tuple/castingTuple.ts(28,10): error TS2323: Type '[number, string]' is not comparable to type '[number, number]'. Types of property '1' are incompatible. - Type 'string' is not comparable with type 'number'. -tests/cases/conformance/types/tuple/castingTuple.ts(29,10): error TS2323: Type '[C, D]' is not comparable with type '[A, I]'. + Type 'string' is not comparable to type 'number'. +tests/cases/conformance/types/tuple/castingTuple.ts(29,10): error TS2323: Type '[C, D]' is not comparable to type '[A, I]'. Types of property '0' are incompatible. - Type 'C' is not comparable with type 'A'. + Type 'C' is not comparable to type 'A'. Property 'a' is missing in type 'C'. tests/cases/conformance/types/tuple/castingTuple.ts(30,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'array1' must be of type '{}[]', but here has type 'number[]'. tests/cases/conformance/types/tuple/castingTuple.ts(31,1): error TS2304: Cannot find name 't4'. @@ -39,14 +39,14 @@ tests/cases/conformance/types/tuple/castingTuple.ts(31,1): error TS2304: Cannot // error var t3 = <[number, number]>numStrTuple; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2323: Type '[number, string]' is not comparable with type '[number, number]'. +!!! error TS2323: Type '[number, string]' is not comparable to type '[number, number]'. !!! error TS2323: Types of property '1' are incompatible. -!!! error TS2323: Type 'string' is not comparable with type 'number'. +!!! error TS2323: Type 'string' is not comparable to type 'number'. var t9 = <[A, I]>classCDTuple; ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2323: Type '[C, D]' is not comparable with type '[A, I]'. +!!! error TS2323: Type '[C, D]' is not comparable to type '[A, I]'. !!! error TS2323: Types of property '0' are incompatible. -!!! error TS2323: Type 'C' is not comparable with type 'A'. +!!! error TS2323: Type 'C' is not comparable to type 'A'. !!! error TS2323: Property 'a' is missing in type 'C'. var array1 = numStrTuple; ~~~~~~ diff --git a/tests/baselines/reference/contextualTyping39.errors.txt b/tests/baselines/reference/contextualTyping39.errors.txt index 844f302cb59..bb797c6a43e 100644 --- a/tests/baselines/reference/contextualTyping39.errors.txt +++ b/tests/baselines/reference/contextualTyping39.errors.txt @@ -1,9 +1,9 @@ -tests/cases/compiler/contextualTyping39.ts(1,11): error TS2323: Type '() => string' is not comparable with type '() => number'. - Type 'string' is not comparable with type 'number'. +tests/cases/compiler/contextualTyping39.ts(1,11): error TS2323: Type '() => string' is not comparable to type '() => number'. + Type 'string' is not comparable to type 'number'. ==== tests/cases/compiler/contextualTyping39.ts (1 errors) ==== var foo = <{ (): number; }> function() { return "err"; }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2323: Type '() => string' is not comparable with type '() => number'. -!!! error TS2323: Type 'string' is not comparable with type 'number'. \ No newline at end of file +!!! error TS2323: Type '() => string' is not comparable to type '() => number'. +!!! error TS2323: Type 'string' is not comparable to type 'number'. \ No newline at end of file diff --git a/tests/baselines/reference/contextualTyping41.errors.txt b/tests/baselines/reference/contextualTyping41.errors.txt index 2f1ac620b7a..e3261e11843 100644 --- a/tests/baselines/reference/contextualTyping41.errors.txt +++ b/tests/baselines/reference/contextualTyping41.errors.txt @@ -1,9 +1,9 @@ -tests/cases/compiler/contextualTyping41.ts(1,11): error TS2323: Type '() => string' is not comparable with type '{ (): number; (i: number): number; }'. - Type 'string' is not comparable with type 'number'. +tests/cases/compiler/contextualTyping41.ts(1,11): error TS2323: Type '() => string' is not comparable to type '{ (): number; (i: number): number; }'. + Type 'string' is not comparable to type 'number'. ==== tests/cases/compiler/contextualTyping41.ts (1 errors) ==== var foo = <{():number; (i:number):number; }> (function(){return "err";}); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2323: Type '() => string' is not comparable with type '{ (): number; (i: number): number; }'. -!!! error TS2323: Type 'string' is not comparable with type 'number'. \ No newline at end of file +!!! error TS2323: Type '() => string' is not comparable to type '{ (): number; (i: number): number; }'. +!!! error TS2323: Type 'string' is not comparable to type 'number'. \ No newline at end of file diff --git a/tests/baselines/reference/defaultArgsInFunctionExpressions.errors.txt b/tests/baselines/reference/defaultArgsInFunctionExpressions.errors.txt index 82851017207..7b7166843c3 100644 --- a/tests/baselines/reference/defaultArgsInFunctionExpressions.errors.txt +++ b/tests/baselines/reference/defaultArgsInFunctionExpressions.errors.txt @@ -2,9 +2,9 @@ tests/cases/compiler/defaultArgsInFunctionExpressions.ts(4,19): error TS2345: Ar tests/cases/compiler/defaultArgsInFunctionExpressions.ts(5,1): error TS2322: Type 'number' is not assignable to type 'string'. tests/cases/compiler/defaultArgsInFunctionExpressions.ts(8,20): error TS2322: Type 'number' is not assignable to type 'string'. tests/cases/compiler/defaultArgsInFunctionExpressions.ts(11,1): error TS2322: Type 'string' is not assignable to type 'number'. -tests/cases/compiler/defaultArgsInFunctionExpressions.ts(14,51): error TS2323: Type 'string' is not comparable with type 'number'. +tests/cases/compiler/defaultArgsInFunctionExpressions.ts(14,51): error TS2323: Type 'string' is not comparable to type 'number'. tests/cases/compiler/defaultArgsInFunctionExpressions.ts(17,41): error TS2322: Type 'string' is not assignable to type 'number'. -tests/cases/compiler/defaultArgsInFunctionExpressions.ts(20,62): error TS2323: Type 'string' is not comparable with type 'number'. +tests/cases/compiler/defaultArgsInFunctionExpressions.ts(20,62): error TS2323: Type 'string' is not comparable to type 'number'. tests/cases/compiler/defaultArgsInFunctionExpressions.ts(28,15): error TS2304: Cannot find name 'T'. @@ -32,7 +32,7 @@ tests/cases/compiler/defaultArgsInFunctionExpressions.ts(28,15): error TS2304: C // Contextually type the default arg with the type annotation var f3 = function (a: (s: string) => any = (s) => s) { }; ~~~~~~~~~ -!!! error TS2323: Type 'string' is not comparable with type 'number'. +!!! error TS2323: Type 'string' is not comparable to type 'number'. // Type check using the function's contextual type var f4: (a: number) => void = function (a = "") { }; @@ -42,7 +42,7 @@ tests/cases/compiler/defaultArgsInFunctionExpressions.ts(28,15): error TS2304: C // Contextually type the default arg using the function's contextual type var f5: (a: (s: string) => any) => void = function (a = s => s) { }; ~~~~~~~~~ -!!! error TS2323: Type 'string' is not comparable with type 'number'. +!!! error TS2323: Type 'string' is not comparable to type 'number'. // Instantiated module module T { } diff --git a/tests/baselines/reference/fuzzy.errors.txt b/tests/baselines/reference/fuzzy.errors.txt index f79bc817a10..f39b520759c 100644 --- a/tests/baselines/reference/fuzzy.errors.txt +++ b/tests/baselines/reference/fuzzy.errors.txt @@ -4,7 +4,7 @@ tests/cases/compiler/fuzzy.ts(21,20): error TS2322: Type '{ anything: number; on Types of property 'oneI' are incompatible. Type 'this' is not assignable to type 'I'. Type 'C' is not assignable to type 'I'. -tests/cases/compiler/fuzzy.ts(25,20): error TS2323: Type '{ oneI: this; }' is not comparable with type 'R'. +tests/cases/compiler/fuzzy.ts(25,20): error TS2323: Type '{ oneI: this; }' is not comparable to type 'R'. Property 'anything' is missing in type '{ oneI: this; }'. @@ -43,7 +43,7 @@ tests/cases/compiler/fuzzy.ts(25,20): error TS2323: Type '{ oneI: this; }' is no worksToo():R { return ({ oneI: this }); ~~~~~~~~~~~~~~~~~~~ -!!! error TS2323: Type '{ oneI: this; }' is not comparable with type 'R'. +!!! error TS2323: Type '{ oneI: this; }' is not comparable to type 'R'. !!! error TS2323: Property 'anything' is missing in type '{ oneI: this; }'. } } diff --git a/tests/baselines/reference/genericTypeAssertions1.errors.txt b/tests/baselines/reference/genericTypeAssertions1.errors.txt index 1e4439ce2ae..3e0157f9863 100644 --- a/tests/baselines/reference/genericTypeAssertions1.errors.txt +++ b/tests/baselines/reference/genericTypeAssertions1.errors.txt @@ -2,8 +2,8 @@ tests/cases/compiler/genericTypeAssertions1.ts(3,5): error TS2322: Type 'A>' is not assignable to type 'A'. Type 'A' is not assignable to type 'number'. -tests/cases/compiler/genericTypeAssertions1.ts(4,21): error TS2323: Type 'A' is not comparable with type 'A>'. - Type 'number' is not comparable with type 'A'. +tests/cases/compiler/genericTypeAssertions1.ts(4,21): error TS2323: Type 'A' is not comparable to type 'A>'. + Type 'number' is not comparable to type 'A'. ==== tests/cases/compiler/genericTypeAssertions1.ts (3 errors) ==== @@ -18,5 +18,5 @@ tests/cases/compiler/genericTypeAssertions1.ts(4,21): error TS2323: Type 'A>' is not assignable to type 'A'. !!! error TS2322: Type 'A' is not assignable to type 'number'. ~~~~~~~~~~~~~~~~~ -!!! error TS2323: Type 'A' is not comparable with type 'A>'. -!!! error TS2323: Type 'number' is not comparable with type 'A'. \ No newline at end of file +!!! error TS2323: Type 'A' is not comparable to type 'A>'. +!!! error TS2323: Type 'number' is not comparable to type 'A'. \ No newline at end of file diff --git a/tests/baselines/reference/genericTypeAssertions2.errors.txt b/tests/baselines/reference/genericTypeAssertions2.errors.txt index ce20955ec1a..908255b1d33 100644 --- a/tests/baselines/reference/genericTypeAssertions2.errors.txt +++ b/tests/baselines/reference/genericTypeAssertions2.errors.txt @@ -5,7 +5,7 @@ tests/cases/compiler/genericTypeAssertions2.ts(10,5): error TS2322: Type 'B' is not assignable to type 'B'. Property 'bar' is missing in type 'A'. -tests/cases/compiler/genericTypeAssertions2.ts(13,21): error TS2323: Type 'undefined[]' is not comparable with type 'A'. +tests/cases/compiler/genericTypeAssertions2.ts(13,21): error TS2323: Type 'undefined[]' is not comparable to type 'A'. Property 'foo' is missing in type 'undefined[]'. @@ -33,5 +33,5 @@ tests/cases/compiler/genericTypeAssertions2.ts(13,21): error TS2323: Type 'undef var r4: A = >new A(); var r5: A = >[]; // error ~~~~~~~~~~~~~ -!!! error TS2323: Type 'undefined[]' is not comparable with type 'A'. +!!! error TS2323: Type 'undefined[]' is not comparable to type 'A'. !!! error TS2323: Property 'foo' is missing in type 'undefined[]'. \ No newline at end of file diff --git a/tests/baselines/reference/genericTypeAssertions4.errors.txt b/tests/baselines/reference/genericTypeAssertions4.errors.txt index 3456b233f67..cffacb6b0dc 100644 --- a/tests/baselines/reference/genericTypeAssertions4.errors.txt +++ b/tests/baselines/reference/genericTypeAssertions4.errors.txt @@ -1,8 +1,8 @@ tests/cases/compiler/genericTypeAssertions4.ts(19,5): error TS2322: Type 'A' is not assignable to type 'T'. tests/cases/compiler/genericTypeAssertions4.ts(20,5): error TS2322: Type 'B' is not assignable to type 'T'. tests/cases/compiler/genericTypeAssertions4.ts(21,5): error TS2322: Type 'C' is not assignable to type 'T'. -tests/cases/compiler/genericTypeAssertions4.ts(23,9): error TS2323: Type 'B' is not comparable with type 'T'. -tests/cases/compiler/genericTypeAssertions4.ts(24,9): error TS2323: Type 'C' is not comparable with type 'T'. +tests/cases/compiler/genericTypeAssertions4.ts(23,9): error TS2323: Type 'B' is not comparable to type 'T'. +tests/cases/compiler/genericTypeAssertions4.ts(24,9): error TS2323: Type 'C' is not comparable to type 'T'. ==== tests/cases/compiler/genericTypeAssertions4.ts (5 errors) ==== @@ -36,8 +36,8 @@ tests/cases/compiler/genericTypeAssertions4.ts(24,9): error TS2323: Type 'C' is y = a; y = b; // error: cannot convert B to T ~~~~ -!!! error TS2323: Type 'B' is not comparable with type 'T'. +!!! error TS2323: Type 'B' is not comparable to type 'T'. y = c; // error: cannot convert C to T ~~~~ -!!! error TS2323: Type 'C' is not comparable with type 'T'. +!!! error TS2323: Type 'C' is not comparable to type 'T'. } \ No newline at end of file diff --git a/tests/baselines/reference/genericTypeAssertions5.errors.txt b/tests/baselines/reference/genericTypeAssertions5.errors.txt index b621decb062..f7f2be41825 100644 --- a/tests/baselines/reference/genericTypeAssertions5.errors.txt +++ b/tests/baselines/reference/genericTypeAssertions5.errors.txt @@ -1,8 +1,8 @@ tests/cases/compiler/genericTypeAssertions5.ts(19,5): error TS2322: Type 'A' is not assignable to type 'T'. tests/cases/compiler/genericTypeAssertions5.ts(20,5): error TS2322: Type 'B' is not assignable to type 'T'. tests/cases/compiler/genericTypeAssertions5.ts(21,5): error TS2322: Type 'C' is not assignable to type 'T'. -tests/cases/compiler/genericTypeAssertions5.ts(23,9): error TS2323: Type 'B' is not comparable with type 'T'. -tests/cases/compiler/genericTypeAssertions5.ts(24,9): error TS2323: Type 'C' is not comparable with type 'T'. +tests/cases/compiler/genericTypeAssertions5.ts(23,9): error TS2323: Type 'B' is not comparable to type 'T'. +tests/cases/compiler/genericTypeAssertions5.ts(24,9): error TS2323: Type 'C' is not comparable to type 'T'. ==== tests/cases/compiler/genericTypeAssertions5.ts (5 errors) ==== @@ -36,8 +36,8 @@ tests/cases/compiler/genericTypeAssertions5.ts(24,9): error TS2323: Type 'C' is y = a; y = b; // error: cannot convert B to T ~~~~ -!!! error TS2323: Type 'B' is not comparable with type 'T'. +!!! error TS2323: Type 'B' is not comparable to type 'T'. y = c; // error: cannot convert C to T ~~~~ -!!! error TS2323: Type 'C' is not comparable with type 'T'. +!!! error TS2323: Type 'C' is not comparable to type 'T'. } \ No newline at end of file diff --git a/tests/baselines/reference/genericTypeAssertions6.errors.txt b/tests/baselines/reference/genericTypeAssertions6.errors.txt index 3637a5cbb5b..4ea7d3602eb 100644 --- a/tests/baselines/reference/genericTypeAssertions6.errors.txt +++ b/tests/baselines/reference/genericTypeAssertions6.errors.txt @@ -1,7 +1,7 @@ -tests/cases/compiler/genericTypeAssertions6.ts(8,13): error TS2323: Type 'U' is not comparable with type 'T'. -tests/cases/compiler/genericTypeAssertions6.ts(9,13): error TS2323: Type 'T' is not comparable with type 'U'. -tests/cases/compiler/genericTypeAssertions6.ts(19,17): error TS2323: Type 'U' is not comparable with type 'T'. - Type 'Date' is not comparable with type 'T'. +tests/cases/compiler/genericTypeAssertions6.ts(8,13): error TS2323: Type 'U' is not comparable to type 'T'. +tests/cases/compiler/genericTypeAssertions6.ts(9,13): error TS2323: Type 'T' is not comparable to type 'U'. +tests/cases/compiler/genericTypeAssertions6.ts(19,17): error TS2323: Type 'U' is not comparable to type 'T'. + Type 'Date' is not comparable to type 'T'. ==== tests/cases/compiler/genericTypeAssertions6.ts (3 errors) ==== @@ -14,10 +14,10 @@ tests/cases/compiler/genericTypeAssertions6.ts(19,17): error TS2323: Type 'U' is f(x: T, y: U) { x = y; ~~~~ -!!! error TS2323: Type 'U' is not comparable with type 'T'. +!!! error TS2323: Type 'U' is not comparable to type 'T'. y = x; ~~~~ -!!! error TS2323: Type 'T' is not comparable with type 'U'. +!!! error TS2323: Type 'T' is not comparable to type 'U'. } } @@ -29,8 +29,8 @@ tests/cases/compiler/genericTypeAssertions6.ts(19,17): error TS2323: Type 'U' is var d = new Date(); var e = new Date(); ~~~~~~~~~~~~~~~~ -!!! error TS2323: Type 'U' is not comparable with type 'T'. -!!! error TS2323: Type 'Date' is not comparable with type 'T'. +!!! error TS2323: Type 'U' is not comparable to type 'T'. +!!! error TS2323: Type 'Date' is not comparable to type 'T'. } } diff --git a/tests/baselines/reference/intTypeCheck.errors.txt b/tests/baselines/reference/intTypeCheck.errors.txt index defcc276844..175c5ea7979 100644 --- a/tests/baselines/reference/intTypeCheck.errors.txt +++ b/tests/baselines/reference/intTypeCheck.errors.txt @@ -61,7 +61,7 @@ tests/cases/compiler/intTypeCheck.ts(176,22): error TS2304: Cannot find name 'i6 tests/cases/compiler/intTypeCheck.ts(177,17): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. tests/cases/compiler/intTypeCheck.ts(182,5): error TS2322: Type '{}' is not assignable to type 'i7'. tests/cases/compiler/intTypeCheck.ts(183,5): error TS2322: Type 'Object' is not assignable to type 'i7'. -tests/cases/compiler/intTypeCheck.ts(185,17): error TS2323: Type 'Base' is not comparable with type 'i7'. +tests/cases/compiler/intTypeCheck.ts(185,17): error TS2323: Type 'Base' is not comparable to type 'i7'. tests/cases/compiler/intTypeCheck.ts(187,5): error TS2322: Type '() => void' is not assignable to type 'i7'. tests/cases/compiler/intTypeCheck.ts(190,5): error TS2322: Type 'boolean' is not assignable to type 'i7'. tests/cases/compiler/intTypeCheck.ts(190,21): error TS1109: Expression expected. @@ -377,7 +377,7 @@ tests/cases/compiler/intTypeCheck.ts(205,17): error TS2351: Cannot use 'new' wit var obj69: i7 = new obj66; var obj70: i7 = new Base; ~~~~~~~~~~~~ -!!! error TS2323: Type 'Base' is not comparable with type 'i7'. +!!! error TS2323: Type 'Base' is not comparable to type 'i7'. var obj71: i7 = null; var obj72: i7 = function () { }; ~~~~~ diff --git a/tests/baselines/reference/literals-negative.errors.txt b/tests/baselines/reference/literals-negative.errors.txt index f2a56614cbc..40a00989717 100644 --- a/tests/baselines/reference/literals-negative.errors.txt +++ b/tests/baselines/reference/literals-negative.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/literals-negative.ts(5,9): error TS2323: Type 'number' is not comparable with type 'boolean'. +tests/cases/compiler/literals-negative.ts(5,9): error TS2323: Type 'number' is not comparable to type 'boolean'. ==== tests/cases/compiler/literals-negative.ts (1 errors) ==== @@ -8,7 +8,7 @@ tests/cases/compiler/literals-negative.ts(5,9): error TS2323: Type 'number' is n var s = (null); var b = (n); ~~~~~~~~~~~~ -!!! error TS2323: Type 'number' is not comparable with type 'boolean'. +!!! error TS2323: Type 'number' is not comparable to type 'boolean'. function isVoid() : void { } diff --git a/tests/baselines/reference/noImplicitAnyInCastExpression.errors.txt b/tests/baselines/reference/noImplicitAnyInCastExpression.errors.txt index 333a940cc37..35b11dc5b61 100644 --- a/tests/baselines/reference/noImplicitAnyInCastExpression.errors.txt +++ b/tests/baselines/reference/noImplicitAnyInCastExpression.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/noImplicitAnyInCastExpression.ts(16,2): error TS2323: Type '{ c: null; }' is not comparable with type 'IFoo'. +tests/cases/compiler/noImplicitAnyInCastExpression.ts(16,2): error TS2323: Type '{ c: null; }' is not comparable to type 'IFoo'. Property 'a' is missing in type '{ c: null; }'. @@ -20,5 +20,5 @@ tests/cases/compiler/noImplicitAnyInCastExpression.ts(16,2): error TS2323: Type // Neither types is assignable to each other ({ c: null }); ~~~~~~~~~~~~~~~~~ -!!! error TS2323: Type '{ c: null; }' is not comparable with type 'IFoo'. +!!! error TS2323: Type '{ c: null; }' is not comparable to type 'IFoo'. !!! error TS2323: Property 'a' is missing in type '{ c: null; }'. \ No newline at end of file diff --git a/tests/baselines/reference/objectTypesIdentityWithPrivates3.errors.txt b/tests/baselines/reference/objectTypesIdentityWithPrivates3.errors.txt index 6bd4dfd0544..b74518ad062 100644 --- a/tests/baselines/reference/objectTypesIdentityWithPrivates3.errors.txt +++ b/tests/baselines/reference/objectTypesIdentityWithPrivates3.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/types/typeRelationships/typeAndMemberIdentity/objectTypesIdentityWithPrivates3.ts(25,1): error TS2323: Type 'C3' is not comparable with type 'C4'. +tests/cases/conformance/types/typeRelationships/typeAndMemberIdentity/objectTypesIdentityWithPrivates3.ts(25,1): error TS2323: Type 'C3' is not comparable to type 'C4'. Property 'y' is missing in type 'C3'. @@ -29,5 +29,5 @@ tests/cases/conformance/types/typeRelationships/typeAndMemberIdentity/objectType var c3: C3; c3; // Should fail (private x originates in the same declaration, but different types) ~~~~~~ -!!! error TS2323: Type 'C3' is not comparable with type 'C4'. +!!! error TS2323: Type 'C3' is not comparable to type 'C4'. !!! error TS2323: Property 'y' is missing in type 'C3'. \ No newline at end of file diff --git a/tests/baselines/reference/switchAssignmentCompat.errors.txt b/tests/baselines/reference/switchAssignmentCompat.errors.txt index cdfcc423f03..2225c711863 100644 --- a/tests/baselines/reference/switchAssignmentCompat.errors.txt +++ b/tests/baselines/reference/switchAssignmentCompat.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/switchAssignmentCompat.ts(4,10): error TS2323: Type 'typeof Foo' is not comparable with type 'number'. +tests/cases/compiler/switchAssignmentCompat.ts(4,10): error TS2323: Type 'typeof Foo' is not comparable to type 'number'. ==== tests/cases/compiler/switchAssignmentCompat.ts (1 errors) ==== @@ -7,6 +7,6 @@ tests/cases/compiler/switchAssignmentCompat.ts(4,10): error TS2323: Type 'typeof switch (0) { case Foo: break; // Error expected ~~~ -!!! error TS2323: Type 'typeof Foo' is not comparable with type 'number'. +!!! error TS2323: Type 'typeof Foo' is not comparable to type 'number'. } \ No newline at end of file diff --git a/tests/baselines/reference/switchCaseWithIntersectionTypes01.errors.txt b/tests/baselines/reference/switchCaseWithIntersectionTypes01.errors.txt index 417d4394bd8..30e50c2a12d 100644 --- a/tests/baselines/reference/switchCaseWithIntersectionTypes01.errors.txt +++ b/tests/baselines/reference/switchCaseWithIntersectionTypes01.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithIntersectionTypes01.ts(19,10): error TS2323: Type 'number & boolean' is not comparable with type 'string & number'. - Type 'number & boolean' is not comparable with type 'string'. - Type 'boolean' is not comparable with type 'string'. -tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithIntersectionTypes01.ts(23,10): error TS2323: Type 'boolean' is not comparable with type 'string & number'. - Type 'boolean' is not comparable with type 'string'. +tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithIntersectionTypes01.ts(19,10): error TS2323: Type 'number & boolean' is not comparable to type 'string & number'. + Type 'number & boolean' is not comparable to type 'string'. + Type 'boolean' is not comparable to type 'string'. +tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithIntersectionTypes01.ts(23,10): error TS2323: Type 'boolean' is not comparable to type 'string & number'. + Type 'boolean' is not comparable to type 'string'. ==== tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithIntersectionTypes01.ts (2 errors) ==== @@ -26,15 +26,15 @@ tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithInterse // Overlap in constituents case numAndBool: ~~~~~~~~~~ -!!! error TS2323: Type 'number & boolean' is not comparable with type 'string & number'. -!!! error TS2323: Type 'number & boolean' is not comparable with type 'string'. -!!! error TS2323: Type 'boolean' is not comparable with type 'string'. +!!! error TS2323: Type 'number & boolean' is not comparable to type 'string & number'. +!!! error TS2323: Type 'number & boolean' is not comparable to type 'string'. +!!! error TS2323: Type 'boolean' is not comparable to type 'string'. break; // No relation case bool: ~~~~ -!!! error TS2323: Type 'boolean' is not comparable with type 'string & number'. -!!! error TS2323: Type 'boolean' is not comparable with type 'string'. +!!! error TS2323: Type 'boolean' is not comparable to type 'string & number'. +!!! error TS2323: Type 'boolean' is not comparable to type 'string'. break; } \ No newline at end of file diff --git a/tests/baselines/reference/switchCaseWithUnionTypes01.errors.txt b/tests/baselines/reference/switchCaseWithUnionTypes01.errors.txt index 3fbcb4c4658..fe5d9175fc7 100644 --- a/tests/baselines/reference/switchCaseWithUnionTypes01.errors.txt +++ b/tests/baselines/reference/switchCaseWithUnionTypes01.errors.txt @@ -1,5 +1,5 @@ -tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithUnionTypes01.ts(23,10): error TS2323: Type 'boolean' is not comparable with type 'string | number'. - Type 'boolean' is not comparable with type 'number'. +tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithUnionTypes01.ts(23,10): error TS2323: Type 'boolean' is not comparable to type 'string | number'. + Type 'boolean' is not comparable to type 'number'. ==== tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithUnionTypes01.ts (1 errors) ==== @@ -27,7 +27,7 @@ tests/cases/conformance/types/typeRelationships/comparable/switchCaseWithUnionTy // No relation case bool: ~~~~ -!!! error TS2323: Type 'boolean' is not comparable with type 'string | number'. -!!! error TS2323: Type 'boolean' is not comparable with type 'number'. +!!! error TS2323: Type 'boolean' is not comparable to type 'string | number'. +!!! error TS2323: Type 'boolean' is not comparable to type 'number'. break; } \ No newline at end of file diff --git a/tests/baselines/reference/switchCasesExpressionTypeMismatch.errors.txt b/tests/baselines/reference/switchCasesExpressionTypeMismatch.errors.txt index c3009179995..81e5137546a 100644 --- a/tests/baselines/reference/switchCasesExpressionTypeMismatch.errors.txt +++ b/tests/baselines/reference/switchCasesExpressionTypeMismatch.errors.txt @@ -1,6 +1,6 @@ -tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(4,10): error TS2323: Type 'typeof Foo' is not comparable with type 'number'. -tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(5,10): error TS2323: Type 'string' is not comparable with type 'number'. -tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(7,10): error TS2323: Type 'boolean' is not comparable with type 'number'. +tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(4,10): error TS2323: Type 'typeof Foo' is not comparable to type 'number'. +tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(5,10): error TS2323: Type 'string' is not comparable to type 'number'. +tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(7,10): error TS2323: Type 'boolean' is not comparable to type 'number'. ==== tests/cases/compiler/switchCasesExpressionTypeMismatch.ts (3 errors) ==== @@ -9,14 +9,14 @@ tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(7,10): error TS2323: T switch (0) { case Foo: break; // Error ~~~ -!!! error TS2323: Type 'typeof Foo' is not comparable with type 'number'. +!!! error TS2323: Type 'typeof Foo' is not comparable to type 'number'. case "sss": break; // Error ~~~~~ -!!! error TS2323: Type 'string' is not comparable with type 'number'. +!!! error TS2323: Type 'string' is not comparable to type 'number'. case 123: break; // No Error case true: break; // Error ~~~~ -!!! error TS2323: Type 'boolean' is not comparable with type 'number'. +!!! error TS2323: Type 'boolean' is not comparable to type 'number'. } var s: any = 0; diff --git a/tests/baselines/reference/switchStatements.errors.txt b/tests/baselines/reference/switchStatements.errors.txt index eddc9eaa833..3ed58a6a65b 100644 --- a/tests/baselines/reference/switchStatements.errors.txt +++ b/tests/baselines/reference/switchStatements.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/statements/switchStatements/switchStatements.ts(35,20): error TS2323: Type '{ id: number; name: string; }' is not comparable with type 'C'. +tests/cases/conformance/statements/switchStatements/switchStatements.ts(35,20): error TS2323: Type '{ id: number; name: string; }' is not comparable to type 'C'. Object literal may only specify known properties, and 'name' does not exist in type 'C'. @@ -39,7 +39,7 @@ tests/cases/conformance/statements/switchStatements/switchStatements.ts(35,20): case new D(): case { id: 12, name: '' }: ~~~~~~~~ -!!! error TS2323: Type '{ id: number; name: string; }' is not comparable with type 'C'. +!!! error TS2323: Type '{ id: number; name: string; }' is not comparable to type 'C'. !!! error TS2323: Object literal may only specify known properties, and 'name' does not exist in type 'C'. case new C(): } diff --git a/tests/baselines/reference/typeAssertions.errors.txt b/tests/baselines/reference/typeAssertions.errors.txt index 1e9e45171f6..da2dcbd8877 100644 --- a/tests/baselines/reference/typeAssertions.errors.txt +++ b/tests/baselines/reference/typeAssertions.errors.txt @@ -1,11 +1,11 @@ tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(5,5): error TS2346: Supplied parameters do not match any signature of call target. -tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(31,12): error TS2323: Type 'SomeOther' is not comparable with type 'SomeBase'. +tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(31,12): error TS2323: Type 'SomeOther' is not comparable to type 'SomeBase'. Property 'p' is missing in type 'SomeOther'. -tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(35,15): error TS2323: Type 'SomeOther' is not comparable with type 'SomeDerived'. +tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(35,15): error TS2323: Type 'SomeOther' is not comparable to type 'SomeDerived'. Property 'x' is missing in type 'SomeOther'. -tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(37,13): error TS2323: Type 'SomeDerived' is not comparable with type 'SomeOther'. +tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(37,13): error TS2323: Type 'SomeDerived' is not comparable to type 'SomeOther'. Property 'q' is missing in type 'SomeDerived'. -tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(38,13): error TS2323: Type 'SomeBase' is not comparable with type 'SomeOther'. +tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(38,13): error TS2323: Type 'SomeBase' is not comparable to type 'SomeOther'. Property 'q' is missing in type 'SomeBase'. @@ -44,23 +44,23 @@ tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(38,13): err someBase = someBase; someBase = someOther; // Error ~~~~~~~~~~~~~~~~~~~ -!!! error TS2323: Type 'SomeOther' is not comparable with type 'SomeBase'. +!!! error TS2323: Type 'SomeOther' is not comparable to type 'SomeBase'. !!! error TS2323: Property 'p' is missing in type 'SomeOther'. someDerived = someDerived; someDerived = someBase; someDerived = someOther; // Error ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2323: Type 'SomeOther' is not comparable with type 'SomeDerived'. +!!! error TS2323: Type 'SomeOther' is not comparable to type 'SomeDerived'. !!! error TS2323: Property 'x' is missing in type 'SomeOther'. someOther = someDerived; // Error ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2323: Type 'SomeDerived' is not comparable with type 'SomeOther'. +!!! error TS2323: Type 'SomeDerived' is not comparable to type 'SomeOther'. !!! error TS2323: Property 'q' is missing in type 'SomeDerived'. someOther = someBase; // Error ~~~~~~~~~~~~~~~~~~~ -!!! error TS2323: Type 'SomeBase' is not comparable with type 'SomeOther'. +!!! error TS2323: Type 'SomeBase' is not comparable to type 'SomeOther'. !!! error TS2323: Property 'q' is missing in type 'SomeBase'. someOther = someOther; diff --git a/tests/baselines/reference/typeAssertionsWithIntersectionTypes01.errors.txt b/tests/baselines/reference/typeAssertionsWithIntersectionTypes01.errors.txt index 1b0cd98533d..c663c6a41e4 100644 --- a/tests/baselines/reference/typeAssertionsWithIntersectionTypes01.errors.txt +++ b/tests/baselines/reference/typeAssertionsWithIntersectionTypes01.errors.txt @@ -1,7 +1,7 @@ -tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithIntersectionTypes01.ts(17,9): error TS2323: Type 'I2' is not comparable with type 'I1 & I3'. - Type 'I2' is not comparable with type 'I3'. +tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithIntersectionTypes01.ts(17,9): error TS2323: Type 'I2' is not comparable to type 'I1 & I3'. + Type 'I2' is not comparable to type 'I3'. Property 'p3' is missing in type 'I2'. -tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithIntersectionTypes01.ts(18,9): error TS2323: Type 'I2' is not comparable with type 'I3'. +tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithIntersectionTypes01.ts(18,9): error TS2323: Type 'I2' is not comparable to type 'I3'. ==== tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithIntersectionTypes01.ts (2 errors) ==== @@ -23,12 +23,12 @@ tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithInt var a = z; ~~~~~~~~~~ -!!! error TS2323: Type 'I2' is not comparable with type 'I1 & I3'. -!!! error TS2323: Type 'I2' is not comparable with type 'I3'. +!!! error TS2323: Type 'I2' is not comparable to type 'I1 & I3'. +!!! error TS2323: Type 'I2' is not comparable to type 'I3'. !!! error TS2323: Property 'p3' is missing in type 'I2'. var b = z; ~~~~~ -!!! error TS2323: Type 'I2' is not comparable with type 'I3'. +!!! error TS2323: Type 'I2' is not comparable to type 'I3'. var c = z; var d = y; \ No newline at end of file diff --git a/tests/baselines/reference/typeAssertionsWithUnionTypes01.errors.txt b/tests/baselines/reference/typeAssertionsWithUnionTypes01.errors.txt index 21d1bccdd5d..a25b6bbb832 100644 --- a/tests/baselines/reference/typeAssertionsWithUnionTypes01.errors.txt +++ b/tests/baselines/reference/typeAssertionsWithUnionTypes01.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithUnionTypes01.ts(14,9): error TS2323: Type 'I1' is not comparable with type 'number'. +tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithUnionTypes01.ts(14,9): error TS2323: Type 'I1' is not comparable to type 'number'. ==== tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithUnionTypes01.ts (1 errors) ==== @@ -17,7 +17,7 @@ tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithUni var a = z; var b = z; ~~~~~~~~~ -!!! error TS2323: Type 'I1' is not comparable with type 'number'. +!!! error TS2323: Type 'I1' is not comparable to type 'number'. var c = z; var d = y; \ No newline at end of file From a37b731193a543946272ad58257db8a305fce7e7 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 5 Nov 2015 15:44:51 -0800 Subject: [PATCH 020/274] Changed type assertion error message. --- src/compiler/checker.ts | 2 +- src/compiler/diagnosticMessages.json | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1d859cee660..de11802cc79 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9418,7 +9418,7 @@ namespace ts { let widenedType = getWidenedType(exprType); if (!isTypeComparableTo(targetType, widenedType)) { - checkTypeComparableTo(exprType, targetType, node); + checkTypeComparableTo(exprType, targetType, node, Diagnostics.Type_0_cannot_be_converted_to_type_1); } } return targetType; diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index c295a828175..b5471520d25 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1000,6 +1000,10 @@ "category": "Error", "code": 2351 }, + "Type '{0}' cannot be converted to type '{1}'.": { + "category": "Error", + "code": 2352 + }, "Object literal may only specify known properties, and '{0}' does not exist in type '{1}'.": { "category": "Error", "code": 2353 From e0385a42442d7aa29c27ab66d4d55c1e77f6314a Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 5 Nov 2015 15:45:12 -0800 Subject: [PATCH 021/274] Accepted baselines. --- .../baselines/reference/arrayCast.errors.txt | 8 +++---- .../reference/asOperator2.errors.txt | 4 ++-- .../asOperatorContextualType.errors.txt | 6 ++--- .../reference/asOperatorNames.errors.txt | 4 ++-- .../reference/castingTuple.errors.txt | 18 +++++++------- .../reference/contextualTyping39.errors.txt | 6 ++--- .../reference/contextualTyping41.errors.txt | 6 ++--- ...efaultArgsInFunctionExpressions.errors.txt | 8 +++---- tests/baselines/reference/fuzzy.errors.txt | 6 ++--- .../genericTypeAssertions1.errors.txt | 6 ++--- .../genericTypeAssertions2.errors.txt | 6 ++--- .../genericTypeAssertions4.errors.txt | 8 +++---- .../genericTypeAssertions5.errors.txt | 8 +++---- .../genericTypeAssertions6.errors.txt | 14 +++++------ .../reference/intTypeCheck.errors.txt | 4 ++-- .../reference/literals-negative.errors.txt | 4 ++-- .../noImplicitAnyInCastExpression.errors.txt | 6 ++--- ...bjectTypesIdentityWithPrivates3.errors.txt | 6 ++--- .../reference/typeAssertions.errors.txt | 24 +++++++++---------- ...sertionsWithIntersectionTypes01.errors.txt | 12 +++++----- .../typeAssertionsWithUnionTypes01.errors.txt | 4 ++-- 21 files changed, 84 insertions(+), 84 deletions(-) diff --git a/tests/baselines/reference/arrayCast.errors.txt b/tests/baselines/reference/arrayCast.errors.txt index bb895475a18..61463e5557b 100644 --- a/tests/baselines/reference/arrayCast.errors.txt +++ b/tests/baselines/reference/arrayCast.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/arrayCast.ts(3,23): error TS2323: Type '{ foo: string; }[]' is not comparable to type '{ id: number; }[]'. +tests/cases/compiler/arrayCast.ts(3,23): error TS2352: Type '{ foo: string; }[]' cannot be converted to type '{ id: number; }[]'. Type '{ foo: string; }' is not comparable to type '{ id: number; }'. Object literal may only specify known properties, and 'foo' does not exist in type '{ id: number; }'. @@ -8,9 +8,9 @@ tests/cases/compiler/arrayCast.ts(3,23): error TS2323: Type '{ foo: string; }[]' // has type { foo: string }[], which is not assignable to { id: number }[]. <{ id: number; }[]>[{ foo: "s" }]; ~~~~~~~~ -!!! error TS2323: Type '{ foo: string; }[]' is not comparable to type '{ id: number; }[]'. -!!! error TS2323: Type '{ foo: string; }' is not comparable to type '{ id: number; }'. -!!! error TS2323: Object literal may only specify known properties, and 'foo' does not exist in type '{ id: number; }'. +!!! error TS2352: Type '{ foo: string; }[]' cannot be converted to type '{ id: number; }[]'. +!!! error TS2352: Type '{ foo: string; }' is not comparable to type '{ id: number; }'. +!!! error TS2352: Object literal may only specify known properties, and 'foo' does not exist in type '{ id: number; }'. // Should succeed, as the {} element causes the type of the array to be {}[] <{ id: number; }[]>[{ foo: "s" }, {}]; \ No newline at end of file diff --git a/tests/baselines/reference/asOperator2.errors.txt b/tests/baselines/reference/asOperator2.errors.txt index 0930191aae1..92603c25cb0 100644 --- a/tests/baselines/reference/asOperator2.errors.txt +++ b/tests/baselines/reference/asOperator2.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/expressions/asOperator/asOperator2.ts(1,9): error TS2323: Type 'number' is not comparable to type 'string'. +tests/cases/conformance/expressions/asOperator/asOperator2.ts(1,9): error TS2352: Type 'number' cannot be converted to type 'string'. ==== tests/cases/conformance/expressions/asOperator/asOperator2.ts (1 errors) ==== var x = 23 as string; ~~~~~~~~~~~~ -!!! error TS2323: Type 'number' is not comparable to type 'string'. +!!! error TS2352: Type 'number' cannot be converted to type 'string'. \ No newline at end of file diff --git a/tests/baselines/reference/asOperatorContextualType.errors.txt b/tests/baselines/reference/asOperatorContextualType.errors.txt index 1a6cf43827c..9431d6123e2 100644 --- a/tests/baselines/reference/asOperatorContextualType.errors.txt +++ b/tests/baselines/reference/asOperatorContextualType.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/expressions/asOperator/asOperatorContextualType.ts(2,9): error TS2323: Type '(v: number) => number' is not comparable to type '(x: number) => string'. +tests/cases/conformance/expressions/asOperator/asOperatorContextualType.ts(2,9): error TS2352: Type '(v: number) => number' cannot be converted to type '(x: number) => string'. Type 'number' is not comparable to type 'string'. @@ -6,5 +6,5 @@ tests/cases/conformance/expressions/asOperator/asOperatorContextualType.ts(2,9): // should error var x = (v => v) as (x: number) => string; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2323: Type '(v: number) => number' is not comparable to type '(x: number) => string'. -!!! error TS2323: Type 'number' is not comparable to type 'string'. \ No newline at end of file +!!! error TS2352: Type '(v: number) => number' cannot be converted to type '(x: number) => string'. +!!! error TS2352: Type 'number' is not comparable to type 'string'. \ No newline at end of file diff --git a/tests/baselines/reference/asOperatorNames.errors.txt b/tests/baselines/reference/asOperatorNames.errors.txt index f4ef8a64e2b..4f957791a24 100644 --- a/tests/baselines/reference/asOperatorNames.errors.txt +++ b/tests/baselines/reference/asOperatorNames.errors.txt @@ -1,11 +1,11 @@ -tests/cases/conformance/expressions/asOperator/asOperatorNames.ts(2,9): error TS2323: Type 'number' is not comparable to type 'string'. +tests/cases/conformance/expressions/asOperator/asOperatorNames.ts(2,9): error TS2352: Type 'number' cannot be converted to type 'string'. ==== tests/cases/conformance/expressions/asOperator/asOperatorNames.ts (1 errors) ==== var a = 20; var b = a as string; ~~~~~~~~~~~ -!!! error TS2323: Type 'number' is not comparable to type 'string'. +!!! error TS2352: Type 'number' cannot be converted to type 'string'. var as = "hello"; var as1 = as as string; \ No newline at end of file diff --git a/tests/baselines/reference/castingTuple.errors.txt b/tests/baselines/reference/castingTuple.errors.txt index 4430c932bfc..6d5549c6bf2 100644 --- a/tests/baselines/reference/castingTuple.errors.txt +++ b/tests/baselines/reference/castingTuple.errors.txt @@ -1,7 +1,7 @@ -tests/cases/conformance/types/tuple/castingTuple.ts(28,10): error TS2323: Type '[number, string]' is not comparable to type '[number, number]'. +tests/cases/conformance/types/tuple/castingTuple.ts(28,10): error TS2352: Type '[number, string]' cannot be converted to type '[number, number]'. Types of property '1' are incompatible. Type 'string' is not comparable to type 'number'. -tests/cases/conformance/types/tuple/castingTuple.ts(29,10): error TS2323: Type '[C, D]' is not comparable to type '[A, I]'. +tests/cases/conformance/types/tuple/castingTuple.ts(29,10): error TS2352: Type '[C, D]' cannot be converted to type '[A, I]'. Types of property '0' are incompatible. Type 'C' is not comparable to type 'A'. Property 'a' is missing in type 'C'. @@ -39,15 +39,15 @@ tests/cases/conformance/types/tuple/castingTuple.ts(31,1): error TS2304: Cannot // error var t3 = <[number, number]>numStrTuple; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2323: Type '[number, string]' is not comparable to type '[number, number]'. -!!! error TS2323: Types of property '1' are incompatible. -!!! error TS2323: Type 'string' is not comparable to type 'number'. +!!! error TS2352: Type '[number, string]' cannot be converted to type '[number, number]'. +!!! error TS2352: Types of property '1' are incompatible. +!!! error TS2352: Type 'string' is not comparable to type 'number'. var t9 = <[A, I]>classCDTuple; ~~~~~~~~~~~~~~~~~~~~ -!!! error TS2323: Type '[C, D]' is not comparable to type '[A, I]'. -!!! error TS2323: Types of property '0' are incompatible. -!!! error TS2323: Type 'C' is not comparable to type 'A'. -!!! error TS2323: Property 'a' is missing in type 'C'. +!!! error TS2352: Type '[C, D]' cannot be converted to type '[A, I]'. +!!! error TS2352: Types of property '0' are incompatible. +!!! error TS2352: Type 'C' is not comparable to type 'A'. +!!! error TS2352: Property 'a' is missing in type 'C'. var array1 = numStrTuple; ~~~~~~ !!! error TS2403: Subsequent variable declarations must have the same type. Variable 'array1' must be of type '{}[]', but here has type 'number[]'. diff --git a/tests/baselines/reference/contextualTyping39.errors.txt b/tests/baselines/reference/contextualTyping39.errors.txt index bb797c6a43e..9081480f4ba 100644 --- a/tests/baselines/reference/contextualTyping39.errors.txt +++ b/tests/baselines/reference/contextualTyping39.errors.txt @@ -1,9 +1,9 @@ -tests/cases/compiler/contextualTyping39.ts(1,11): error TS2323: Type '() => string' is not comparable to type '() => number'. +tests/cases/compiler/contextualTyping39.ts(1,11): error TS2352: Type '() => string' cannot be converted to type '() => number'. Type 'string' is not comparable to type 'number'. ==== tests/cases/compiler/contextualTyping39.ts (1 errors) ==== var foo = <{ (): number; }> function() { return "err"; }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2323: Type '() => string' is not comparable to type '() => number'. -!!! error TS2323: Type 'string' is not comparable to type 'number'. \ No newline at end of file +!!! error TS2352: Type '() => string' cannot be converted to type '() => number'. +!!! error TS2352: Type 'string' is not comparable to type 'number'. \ No newline at end of file diff --git a/tests/baselines/reference/contextualTyping41.errors.txt b/tests/baselines/reference/contextualTyping41.errors.txt index e3261e11843..418d435e7fe 100644 --- a/tests/baselines/reference/contextualTyping41.errors.txt +++ b/tests/baselines/reference/contextualTyping41.errors.txt @@ -1,9 +1,9 @@ -tests/cases/compiler/contextualTyping41.ts(1,11): error TS2323: Type '() => string' is not comparable to type '{ (): number; (i: number): number; }'. +tests/cases/compiler/contextualTyping41.ts(1,11): error TS2352: Type '() => string' cannot be converted to type '{ (): number; (i: number): number; }'. Type 'string' is not comparable to type 'number'. ==== tests/cases/compiler/contextualTyping41.ts (1 errors) ==== var foo = <{():number; (i:number):number; }> (function(){return "err";}); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2323: Type '() => string' is not comparable to type '{ (): number; (i: number): number; }'. -!!! error TS2323: Type 'string' is not comparable to type 'number'. \ No newline at end of file +!!! error TS2352: Type '() => string' cannot be converted to type '{ (): number; (i: number): number; }'. +!!! error TS2352: Type 'string' is not comparable to type 'number'. \ No newline at end of file diff --git a/tests/baselines/reference/defaultArgsInFunctionExpressions.errors.txt b/tests/baselines/reference/defaultArgsInFunctionExpressions.errors.txt index 7b7166843c3..60a9e92bc95 100644 --- a/tests/baselines/reference/defaultArgsInFunctionExpressions.errors.txt +++ b/tests/baselines/reference/defaultArgsInFunctionExpressions.errors.txt @@ -2,9 +2,9 @@ tests/cases/compiler/defaultArgsInFunctionExpressions.ts(4,19): error TS2345: Ar tests/cases/compiler/defaultArgsInFunctionExpressions.ts(5,1): error TS2322: Type 'number' is not assignable to type 'string'. tests/cases/compiler/defaultArgsInFunctionExpressions.ts(8,20): error TS2322: Type 'number' is not assignable to type 'string'. tests/cases/compiler/defaultArgsInFunctionExpressions.ts(11,1): error TS2322: Type 'string' is not assignable to type 'number'. -tests/cases/compiler/defaultArgsInFunctionExpressions.ts(14,51): error TS2323: Type 'string' is not comparable to type 'number'. +tests/cases/compiler/defaultArgsInFunctionExpressions.ts(14,51): error TS2352: Type 'string' cannot be converted to type 'number'. tests/cases/compiler/defaultArgsInFunctionExpressions.ts(17,41): error TS2322: Type 'string' is not assignable to type 'number'. -tests/cases/compiler/defaultArgsInFunctionExpressions.ts(20,62): error TS2323: Type 'string' is not comparable to type 'number'. +tests/cases/compiler/defaultArgsInFunctionExpressions.ts(20,62): error TS2352: Type 'string' cannot be converted to type 'number'. tests/cases/compiler/defaultArgsInFunctionExpressions.ts(28,15): error TS2304: Cannot find name 'T'. @@ -32,7 +32,7 @@ tests/cases/compiler/defaultArgsInFunctionExpressions.ts(28,15): error TS2304: C // Contextually type the default arg with the type annotation var f3 = function (a: (s: string) => any = (s) => s) { }; ~~~~~~~~~ -!!! error TS2323: Type 'string' is not comparable to type 'number'. +!!! error TS2352: Type 'string' cannot be converted to type 'number'. // Type check using the function's contextual type var f4: (a: number) => void = function (a = "") { }; @@ -42,7 +42,7 @@ tests/cases/compiler/defaultArgsInFunctionExpressions.ts(28,15): error TS2304: C // Contextually type the default arg using the function's contextual type var f5: (a: (s: string) => any) => void = function (a = s => s) { }; ~~~~~~~~~ -!!! error TS2323: Type 'string' is not comparable to type 'number'. +!!! error TS2352: Type 'string' cannot be converted to type 'number'. // Instantiated module module T { } diff --git a/tests/baselines/reference/fuzzy.errors.txt b/tests/baselines/reference/fuzzy.errors.txt index f39b520759c..19f0ad56a5e 100644 --- a/tests/baselines/reference/fuzzy.errors.txt +++ b/tests/baselines/reference/fuzzy.errors.txt @@ -4,7 +4,7 @@ tests/cases/compiler/fuzzy.ts(21,20): error TS2322: Type '{ anything: number; on Types of property 'oneI' are incompatible. Type 'this' is not assignable to type 'I'. Type 'C' is not assignable to type 'I'. -tests/cases/compiler/fuzzy.ts(25,20): error TS2323: Type '{ oneI: this; }' is not comparable to type 'R'. +tests/cases/compiler/fuzzy.ts(25,20): error TS2352: Type '{ oneI: this; }' cannot be converted to type 'R'. Property 'anything' is missing in type '{ oneI: this; }'. @@ -43,8 +43,8 @@ tests/cases/compiler/fuzzy.ts(25,20): error TS2323: Type '{ oneI: this; }' is no worksToo():R { return ({ oneI: this }); ~~~~~~~~~~~~~~~~~~~ -!!! error TS2323: Type '{ oneI: this; }' is not comparable to type 'R'. -!!! error TS2323: Property 'anything' is missing in type '{ oneI: this; }'. +!!! error TS2352: Type '{ oneI: this; }' cannot be converted to type 'R'. +!!! error TS2352: Property 'anything' is missing in type '{ oneI: this; }'. } } } diff --git a/tests/baselines/reference/genericTypeAssertions1.errors.txt b/tests/baselines/reference/genericTypeAssertions1.errors.txt index 3e0157f9863..aa5f14f5da8 100644 --- a/tests/baselines/reference/genericTypeAssertions1.errors.txt +++ b/tests/baselines/reference/genericTypeAssertions1.errors.txt @@ -2,7 +2,7 @@ tests/cases/compiler/genericTypeAssertions1.ts(3,5): error TS2322: Type 'A>' is not assignable to type 'A'. Type 'A' is not assignable to type 'number'. -tests/cases/compiler/genericTypeAssertions1.ts(4,21): error TS2323: Type 'A' is not comparable to type 'A>'. +tests/cases/compiler/genericTypeAssertions1.ts(4,21): error TS2352: Type 'A' cannot be converted to type 'A>'. Type 'number' is not comparable to type 'A'. @@ -18,5 +18,5 @@ tests/cases/compiler/genericTypeAssertions1.ts(4,21): error TS2323: Type 'A>' is not assignable to type 'A'. !!! error TS2322: Type 'A' is not assignable to type 'number'. ~~~~~~~~~~~~~~~~~ -!!! error TS2323: Type 'A' is not comparable to type 'A>'. -!!! error TS2323: Type 'number' is not comparable to type 'A'. \ No newline at end of file +!!! error TS2352: Type 'A' cannot be converted to type 'A>'. +!!! error TS2352: Type 'number' is not comparable to type 'A'. \ No newline at end of file diff --git a/tests/baselines/reference/genericTypeAssertions2.errors.txt b/tests/baselines/reference/genericTypeAssertions2.errors.txt index 908255b1d33..71848c5be02 100644 --- a/tests/baselines/reference/genericTypeAssertions2.errors.txt +++ b/tests/baselines/reference/genericTypeAssertions2.errors.txt @@ -5,7 +5,7 @@ tests/cases/compiler/genericTypeAssertions2.ts(10,5): error TS2322: Type 'B' is not assignable to type 'B'. Property 'bar' is missing in type 'A'. -tests/cases/compiler/genericTypeAssertions2.ts(13,21): error TS2323: Type 'undefined[]' is not comparable to type 'A'. +tests/cases/compiler/genericTypeAssertions2.ts(13,21): error TS2352: Type 'undefined[]' cannot be converted to type 'A'. Property 'foo' is missing in type 'undefined[]'. @@ -33,5 +33,5 @@ tests/cases/compiler/genericTypeAssertions2.ts(13,21): error TS2323: Type 'undef var r4: A = >new A(); var r5: A = >[]; // error ~~~~~~~~~~~~~ -!!! error TS2323: Type 'undefined[]' is not comparable to type 'A'. -!!! error TS2323: Property 'foo' is missing in type 'undefined[]'. \ No newline at end of file +!!! error TS2352: Type 'undefined[]' cannot be converted to type 'A'. +!!! error TS2352: Property 'foo' is missing in type 'undefined[]'. \ No newline at end of file diff --git a/tests/baselines/reference/genericTypeAssertions4.errors.txt b/tests/baselines/reference/genericTypeAssertions4.errors.txt index cffacb6b0dc..401834930f3 100644 --- a/tests/baselines/reference/genericTypeAssertions4.errors.txt +++ b/tests/baselines/reference/genericTypeAssertions4.errors.txt @@ -1,8 +1,8 @@ tests/cases/compiler/genericTypeAssertions4.ts(19,5): error TS2322: Type 'A' is not assignable to type 'T'. tests/cases/compiler/genericTypeAssertions4.ts(20,5): error TS2322: Type 'B' is not assignable to type 'T'. tests/cases/compiler/genericTypeAssertions4.ts(21,5): error TS2322: Type 'C' is not assignable to type 'T'. -tests/cases/compiler/genericTypeAssertions4.ts(23,9): error TS2323: Type 'B' is not comparable to type 'T'. -tests/cases/compiler/genericTypeAssertions4.ts(24,9): error TS2323: Type 'C' is not comparable to type 'T'. +tests/cases/compiler/genericTypeAssertions4.ts(23,9): error TS2352: Type 'B' cannot be converted to type 'T'. +tests/cases/compiler/genericTypeAssertions4.ts(24,9): error TS2352: Type 'C' cannot be converted to type 'T'. ==== tests/cases/compiler/genericTypeAssertions4.ts (5 errors) ==== @@ -36,8 +36,8 @@ tests/cases/compiler/genericTypeAssertions4.ts(24,9): error TS2323: Type 'C' is y = a; y = b; // error: cannot convert B to T ~~~~ -!!! error TS2323: Type 'B' is not comparable to type 'T'. +!!! error TS2352: Type 'B' cannot be converted to type 'T'. y = c; // error: cannot convert C to T ~~~~ -!!! error TS2323: Type 'C' is not comparable to type 'T'. +!!! error TS2352: Type 'C' cannot be converted to type 'T'. } \ No newline at end of file diff --git a/tests/baselines/reference/genericTypeAssertions5.errors.txt b/tests/baselines/reference/genericTypeAssertions5.errors.txt index f7f2be41825..45f76073363 100644 --- a/tests/baselines/reference/genericTypeAssertions5.errors.txt +++ b/tests/baselines/reference/genericTypeAssertions5.errors.txt @@ -1,8 +1,8 @@ tests/cases/compiler/genericTypeAssertions5.ts(19,5): error TS2322: Type 'A' is not assignable to type 'T'. tests/cases/compiler/genericTypeAssertions5.ts(20,5): error TS2322: Type 'B' is not assignable to type 'T'. tests/cases/compiler/genericTypeAssertions5.ts(21,5): error TS2322: Type 'C' is not assignable to type 'T'. -tests/cases/compiler/genericTypeAssertions5.ts(23,9): error TS2323: Type 'B' is not comparable to type 'T'. -tests/cases/compiler/genericTypeAssertions5.ts(24,9): error TS2323: Type 'C' is not comparable to type 'T'. +tests/cases/compiler/genericTypeAssertions5.ts(23,9): error TS2352: Type 'B' cannot be converted to type 'T'. +tests/cases/compiler/genericTypeAssertions5.ts(24,9): error TS2352: Type 'C' cannot be converted to type 'T'. ==== tests/cases/compiler/genericTypeAssertions5.ts (5 errors) ==== @@ -36,8 +36,8 @@ tests/cases/compiler/genericTypeAssertions5.ts(24,9): error TS2323: Type 'C' is y = a; y = b; // error: cannot convert B to T ~~~~ -!!! error TS2323: Type 'B' is not comparable to type 'T'. +!!! error TS2352: Type 'B' cannot be converted to type 'T'. y = c; // error: cannot convert C to T ~~~~ -!!! error TS2323: Type 'C' is not comparable to type 'T'. +!!! error TS2352: Type 'C' cannot be converted to type 'T'. } \ No newline at end of file diff --git a/tests/baselines/reference/genericTypeAssertions6.errors.txt b/tests/baselines/reference/genericTypeAssertions6.errors.txt index 4ea7d3602eb..1bda683b88a 100644 --- a/tests/baselines/reference/genericTypeAssertions6.errors.txt +++ b/tests/baselines/reference/genericTypeAssertions6.errors.txt @@ -1,6 +1,6 @@ -tests/cases/compiler/genericTypeAssertions6.ts(8,13): error TS2323: Type 'U' is not comparable to type 'T'. -tests/cases/compiler/genericTypeAssertions6.ts(9,13): error TS2323: Type 'T' is not comparable to type 'U'. -tests/cases/compiler/genericTypeAssertions6.ts(19,17): error TS2323: Type 'U' is not comparable to type 'T'. +tests/cases/compiler/genericTypeAssertions6.ts(8,13): error TS2352: Type 'U' cannot be converted to type 'T'. +tests/cases/compiler/genericTypeAssertions6.ts(9,13): error TS2352: Type 'T' cannot be converted to type 'U'. +tests/cases/compiler/genericTypeAssertions6.ts(19,17): error TS2352: Type 'U' cannot be converted to type 'T'. Type 'Date' is not comparable to type 'T'. @@ -14,10 +14,10 @@ tests/cases/compiler/genericTypeAssertions6.ts(19,17): error TS2323: Type 'U' is f(x: T, y: U) { x = y; ~~~~ -!!! error TS2323: Type 'U' is not comparable to type 'T'. +!!! error TS2352: Type 'U' cannot be converted to type 'T'. y = x; ~~~~ -!!! error TS2323: Type 'T' is not comparable to type 'U'. +!!! error TS2352: Type 'T' cannot be converted to type 'U'. } } @@ -29,8 +29,8 @@ tests/cases/compiler/genericTypeAssertions6.ts(19,17): error TS2323: Type 'U' is var d = new Date(); var e = new Date(); ~~~~~~~~~~~~~~~~ -!!! error TS2323: Type 'U' is not comparable to type 'T'. -!!! error TS2323: Type 'Date' is not comparable to type 'T'. +!!! error TS2352: Type 'U' cannot be converted to type 'T'. +!!! error TS2352: Type 'Date' is not comparable to type 'T'. } } diff --git a/tests/baselines/reference/intTypeCheck.errors.txt b/tests/baselines/reference/intTypeCheck.errors.txt index 175c5ea7979..29388521104 100644 --- a/tests/baselines/reference/intTypeCheck.errors.txt +++ b/tests/baselines/reference/intTypeCheck.errors.txt @@ -61,7 +61,7 @@ tests/cases/compiler/intTypeCheck.ts(176,22): error TS2304: Cannot find name 'i6 tests/cases/compiler/intTypeCheck.ts(177,17): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. tests/cases/compiler/intTypeCheck.ts(182,5): error TS2322: Type '{}' is not assignable to type 'i7'. tests/cases/compiler/intTypeCheck.ts(183,5): error TS2322: Type 'Object' is not assignable to type 'i7'. -tests/cases/compiler/intTypeCheck.ts(185,17): error TS2323: Type 'Base' is not comparable to type 'i7'. +tests/cases/compiler/intTypeCheck.ts(185,17): error TS2352: Type 'Base' cannot be converted to type 'i7'. tests/cases/compiler/intTypeCheck.ts(187,5): error TS2322: Type '() => void' is not assignable to type 'i7'. tests/cases/compiler/intTypeCheck.ts(190,5): error TS2322: Type 'boolean' is not assignable to type 'i7'. tests/cases/compiler/intTypeCheck.ts(190,21): error TS1109: Expression expected. @@ -377,7 +377,7 @@ tests/cases/compiler/intTypeCheck.ts(205,17): error TS2351: Cannot use 'new' wit var obj69: i7 = new obj66; var obj70: i7 = new Base; ~~~~~~~~~~~~ -!!! error TS2323: Type 'Base' is not comparable to type 'i7'. +!!! error TS2352: Type 'Base' cannot be converted to type 'i7'. var obj71: i7 = null; var obj72: i7 = function () { }; ~~~~~ diff --git a/tests/baselines/reference/literals-negative.errors.txt b/tests/baselines/reference/literals-negative.errors.txt index 40a00989717..2024066d9f2 100644 --- a/tests/baselines/reference/literals-negative.errors.txt +++ b/tests/baselines/reference/literals-negative.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/literals-negative.ts(5,9): error TS2323: Type 'number' is not comparable to type 'boolean'. +tests/cases/compiler/literals-negative.ts(5,9): error TS2352: Type 'number' cannot be converted to type 'boolean'. ==== tests/cases/compiler/literals-negative.ts (1 errors) ==== @@ -8,7 +8,7 @@ tests/cases/compiler/literals-negative.ts(5,9): error TS2323: Type 'number' is n var s = (null); var b = (n); ~~~~~~~~~~~~ -!!! error TS2323: Type 'number' is not comparable to type 'boolean'. +!!! error TS2352: Type 'number' cannot be converted to type 'boolean'. function isVoid() : void { } diff --git a/tests/baselines/reference/noImplicitAnyInCastExpression.errors.txt b/tests/baselines/reference/noImplicitAnyInCastExpression.errors.txt index 35b11dc5b61..8243a9c68ce 100644 --- a/tests/baselines/reference/noImplicitAnyInCastExpression.errors.txt +++ b/tests/baselines/reference/noImplicitAnyInCastExpression.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/noImplicitAnyInCastExpression.ts(16,2): error TS2323: Type '{ c: null; }' is not comparable to type 'IFoo'. +tests/cases/compiler/noImplicitAnyInCastExpression.ts(16,2): error TS2352: Type '{ c: null; }' cannot be converted to type 'IFoo'. Property 'a' is missing in type '{ c: null; }'. @@ -20,5 +20,5 @@ tests/cases/compiler/noImplicitAnyInCastExpression.ts(16,2): error TS2323: Type // Neither types is assignable to each other ({ c: null }); ~~~~~~~~~~~~~~~~~ -!!! error TS2323: Type '{ c: null; }' is not comparable to type 'IFoo'. -!!! error TS2323: Property 'a' is missing in type '{ c: null; }'. \ No newline at end of file +!!! error TS2352: Type '{ c: null; }' cannot be converted to type 'IFoo'. +!!! error TS2352: Property 'a' is missing in type '{ c: null; }'. \ No newline at end of file diff --git a/tests/baselines/reference/objectTypesIdentityWithPrivates3.errors.txt b/tests/baselines/reference/objectTypesIdentityWithPrivates3.errors.txt index b74518ad062..2342065605b 100644 --- a/tests/baselines/reference/objectTypesIdentityWithPrivates3.errors.txt +++ b/tests/baselines/reference/objectTypesIdentityWithPrivates3.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/types/typeRelationships/typeAndMemberIdentity/objectTypesIdentityWithPrivates3.ts(25,1): error TS2323: Type 'C3' is not comparable to type 'C4'. +tests/cases/conformance/types/typeRelationships/typeAndMemberIdentity/objectTypesIdentityWithPrivates3.ts(25,1): error TS2352: Type 'C3' cannot be converted to type 'C4'. Property 'y' is missing in type 'C3'. @@ -29,5 +29,5 @@ tests/cases/conformance/types/typeRelationships/typeAndMemberIdentity/objectType var c3: C3; c3; // Should fail (private x originates in the same declaration, but different types) ~~~~~~ -!!! error TS2323: Type 'C3' is not comparable to type 'C4'. -!!! error TS2323: Property 'y' is missing in type 'C3'. \ No newline at end of file +!!! error TS2352: Type 'C3' cannot be converted to type 'C4'. +!!! error TS2352: Property 'y' is missing in type 'C3'. \ No newline at end of file diff --git a/tests/baselines/reference/typeAssertions.errors.txt b/tests/baselines/reference/typeAssertions.errors.txt index da2dcbd8877..baabc272bf3 100644 --- a/tests/baselines/reference/typeAssertions.errors.txt +++ b/tests/baselines/reference/typeAssertions.errors.txt @@ -1,11 +1,11 @@ tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(5,5): error TS2346: Supplied parameters do not match any signature of call target. -tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(31,12): error TS2323: Type 'SomeOther' is not comparable to type 'SomeBase'. +tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(31,12): error TS2352: Type 'SomeOther' cannot be converted to type 'SomeBase'. Property 'p' is missing in type 'SomeOther'. -tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(35,15): error TS2323: Type 'SomeOther' is not comparable to type 'SomeDerived'. +tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(35,15): error TS2352: Type 'SomeOther' cannot be converted to type 'SomeDerived'. Property 'x' is missing in type 'SomeOther'. -tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(37,13): error TS2323: Type 'SomeDerived' is not comparable to type 'SomeOther'. +tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(37,13): error TS2352: Type 'SomeDerived' cannot be converted to type 'SomeOther'. Property 'q' is missing in type 'SomeDerived'. -tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(38,13): error TS2323: Type 'SomeBase' is not comparable to type 'SomeOther'. +tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(38,13): error TS2352: Type 'SomeBase' cannot be converted to type 'SomeOther'. Property 'q' is missing in type 'SomeBase'. @@ -44,24 +44,24 @@ tests/cases/conformance/expressions/typeAssertions/typeAssertions.ts(38,13): err someBase = someBase; someBase = someOther; // Error ~~~~~~~~~~~~~~~~~~~ -!!! error TS2323: Type 'SomeOther' is not comparable to type 'SomeBase'. -!!! error TS2323: Property 'p' is missing in type 'SomeOther'. +!!! error TS2352: Type 'SomeOther' cannot be converted to type 'SomeBase'. +!!! error TS2352: Property 'p' is missing in type 'SomeOther'. someDerived = someDerived; someDerived = someBase; someDerived = someOther; // Error ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2323: Type 'SomeOther' is not comparable to type 'SomeDerived'. -!!! error TS2323: Property 'x' is missing in type 'SomeOther'. +!!! error TS2352: Type 'SomeOther' cannot be converted to type 'SomeDerived'. +!!! error TS2352: Property 'x' is missing in type 'SomeOther'. someOther = someDerived; // Error ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2323: Type 'SomeDerived' is not comparable to type 'SomeOther'. -!!! error TS2323: Property 'q' is missing in type 'SomeDerived'. +!!! error TS2352: Type 'SomeDerived' cannot be converted to type 'SomeOther'. +!!! error TS2352: Property 'q' is missing in type 'SomeDerived'. someOther = someBase; // Error ~~~~~~~~~~~~~~~~~~~ -!!! error TS2323: Type 'SomeBase' is not comparable to type 'SomeOther'. -!!! error TS2323: Property 'q' is missing in type 'SomeBase'. +!!! error TS2352: Type 'SomeBase' cannot be converted to type 'SomeOther'. +!!! error TS2352: Property 'q' is missing in type 'SomeBase'. someOther = someOther; diff --git a/tests/baselines/reference/typeAssertionsWithIntersectionTypes01.errors.txt b/tests/baselines/reference/typeAssertionsWithIntersectionTypes01.errors.txt index c663c6a41e4..42ed640e8fc 100644 --- a/tests/baselines/reference/typeAssertionsWithIntersectionTypes01.errors.txt +++ b/tests/baselines/reference/typeAssertionsWithIntersectionTypes01.errors.txt @@ -1,7 +1,7 @@ -tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithIntersectionTypes01.ts(17,9): error TS2323: Type 'I2' is not comparable to type 'I1 & I3'. +tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithIntersectionTypes01.ts(17,9): error TS2352: Type 'I2' cannot be converted to type 'I1 & I3'. Type 'I2' is not comparable to type 'I3'. Property 'p3' is missing in type 'I2'. -tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithIntersectionTypes01.ts(18,9): error TS2323: Type 'I2' is not comparable to type 'I3'. +tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithIntersectionTypes01.ts(18,9): error TS2352: Type 'I2' cannot be converted to type 'I3'. ==== tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithIntersectionTypes01.ts (2 errors) ==== @@ -23,12 +23,12 @@ tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithInt var a = z; ~~~~~~~~~~ -!!! error TS2323: Type 'I2' is not comparable to type 'I1 & I3'. -!!! error TS2323: Type 'I2' is not comparable to type 'I3'. -!!! error TS2323: Property 'p3' is missing in type 'I2'. +!!! error TS2352: Type 'I2' cannot be converted to type 'I1 & I3'. +!!! error TS2352: Type 'I2' is not comparable to type 'I3'. +!!! error TS2352: Property 'p3' is missing in type 'I2'. var b = z; ~~~~~ -!!! error TS2323: Type 'I2' is not comparable to type 'I3'. +!!! error TS2352: Type 'I2' cannot be converted to type 'I3'. var c = z; var d = y; \ No newline at end of file diff --git a/tests/baselines/reference/typeAssertionsWithUnionTypes01.errors.txt b/tests/baselines/reference/typeAssertionsWithUnionTypes01.errors.txt index a25b6bbb832..7bc2a9df9b3 100644 --- a/tests/baselines/reference/typeAssertionsWithUnionTypes01.errors.txt +++ b/tests/baselines/reference/typeAssertionsWithUnionTypes01.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithUnionTypes01.ts(14,9): error TS2323: Type 'I1' is not comparable to type 'number'. +tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithUnionTypes01.ts(14,9): error TS2352: Type 'I1' cannot be converted to type 'number'. ==== tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithUnionTypes01.ts (1 errors) ==== @@ -17,7 +17,7 @@ tests/cases/conformance/types/typeRelationships/comparable/typeAssertionsWithUni var a = z; var b = z; ~~~~~~~~~ -!!! error TS2323: Type 'I1' is not comparable to type 'number'. +!!! error TS2352: Type 'I1' cannot be converted to type 'number'. var c = z; var d = y; \ No newline at end of file From 0a968f0868695953537a656c1a7c36f3bb70f076 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 29 Jan 2016 14:10:43 -0800 Subject: [PATCH 022/274] Parse this type using parameter syntax Syntax is the same as a normal parameter: ```ts function f(this: void, x: number) { } ``` --- src/compiler/parser.ts | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 787a022140f..725092d12c8 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1722,7 +1722,7 @@ namespace ts { }; // Parses a comma-delimited list of elements - function parseDelimitedList(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimeter?: boolean): NodeArray { + function parseDelimitedList(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): NodeArray { const saveParsingContext = parsingContext; parsingContext |= 1 << kind; const result = >[]; @@ -1751,7 +1751,7 @@ namespace ts { // parse errors. For example, this can happen when people do things like use // a semicolon to delimit object literal members. Note: we'll have already // reported an error when we called parseExpected above. - if (considerSemicolonAsDelimeter && token === SyntaxKind.SemicolonToken && !scanner.hasPrecedingLineBreak()) { + if (considerSemicolonAsDelimiter && token === SyntaxKind.SemicolonToken && !scanner.hasPrecedingLineBreak()) { nextToken(); } continue; @@ -2002,7 +2002,7 @@ namespace ts { } function isStartOfParameter(): boolean { - return token === SyntaxKind.DotDotDotToken || isIdentifierOrPattern() || isModifierKind(token) || token === SyntaxKind.AtToken; + return token === SyntaxKind.DotDotDotToken || isIdentifierOrPattern() || isModifierKind(token) || token === SyntaxKind.AtToken || token === SyntaxKind.ThisKeyword; } function setModifiers(node: Node, modifiers: ModifiersArray) { @@ -2014,15 +2014,19 @@ namespace ts { function parseParameter(): ParameterDeclaration { const node = createNode(SyntaxKind.Parameter); + if (token === SyntaxKind.ThisKeyword) { + node.name = createIdentifier(/*isIdentifier*/true, undefined); + node.type = parseParameterType(); + return finishNode(node); + } + node.decorators = parseDecorators(); setModifiers(node, parseModifiers()); node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken); // FormalParameter [Yield,Await]: // BindingElement[?Yield,?Await] - node.name = parseIdentifierOrPattern(); - if (getFullWidth(node.name) === 0 && node.flags === 0 && isModifierKind(token)) { // in cases like // 'use strict' @@ -2060,11 +2064,11 @@ namespace ts { } function fillSignature( - returnToken: SyntaxKind, - yieldContext: boolean, - awaitContext: boolean, - requireCompleteParameterList: boolean, - signature: SignatureDeclaration): void { + returnToken: SyntaxKind, + yieldContext: boolean, + awaitContext: boolean, + requireCompleteParameterList: boolean, + signature: SignatureDeclaration): void { const returnTokenRequired = returnToken === SyntaxKind.EqualsGreaterThanToken; signature.typeParameters = parseTypeParameters(); @@ -2464,7 +2468,7 @@ namespace ts { // ( ... return true; } - if (isIdentifier() || isModifierKind(token)) { + if (isIdentifier() || isModifierKind(token) || token === SyntaxKind.ThisKeyword) { nextToken(); if (token === SyntaxKind.ColonToken || token === SyntaxKind.CommaToken || token === SyntaxKind.QuestionToken || token === SyntaxKind.EqualsToken || @@ -3981,7 +3985,7 @@ namespace ts { node.flags |= NodeFlags.MultiLine; } - node.properties = parseDelimitedList(ParsingContext.ObjectLiteralMembers, parseObjectLiteralElement, /*considerSemicolonAsDelimeter*/ true); + node.properties = parseDelimitedList(ParsingContext.ObjectLiteralMembers, parseObjectLiteralElement, /*considerSemicolonAsDelimiter*/ true); parseExpected(SyntaxKind.CloseBraceToken); return finishNode(node); } From d8a77c00557129f3b24cffb7d35888c8519aaebf Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 29 Jan 2016 14:30:01 -0800 Subject: [PATCH 023/274] Check this type in functions. If `this` is not provided, it defaults to `void` for functions and `this` for methods. The rules for checking are similar to parameter checking, but there's still quite a bit of duplication for this implementation. --- src/compiler/binder.ts | 3 + src/compiler/checker.ts | 161 ++++++++++++++++++++++++++++++++-------- 2 files changed, 134 insertions(+), 30 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index cc81f92fbfc..cbeb35ce56c 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1297,6 +1297,9 @@ namespace ts { // as other properties in the object literal. So we use SymbolFlags.PropertyExcludes // so that it will conflict with any other object literal members with the same // name. + if (options.strictThis) { + seenThisKeyword = true; + } return bindPropertyOrMethodOrAccessor(node, SymbolFlags.Method | ((node).questionToken ? SymbolFlags.Optional : SymbolFlags.None), isObjectLiteralMethod(node) ? SymbolFlags.PropertyExcludes : SymbolFlags.MethodExcludes); case SyntaxKind.FunctionDeclaration: diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a0040982356..3940be5d698 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -131,8 +131,8 @@ namespace ts { const noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); - const anySignature = createSignature(undefined, undefined, emptyArray, anyType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false); - const unknownSignature = createSignature(undefined, undefined, emptyArray, unknownType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false); + const anySignature = createSignature(undefined, undefined, emptyArray, undefined, anyType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false); + const unknownSignature = createSignature(undefined, undefined, emptyArray, undefined, unknownType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false); const enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true); @@ -2194,10 +2194,17 @@ namespace ts { } } - function buildDisplayForParametersAndDelimiters(parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) { + function buildDisplayForParametersAndDelimiters(thisType: Type, parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) { writePunctuation(writer, SyntaxKind.OpenParenToken); + const useThisType = thisType && thisType.symbol; + if (useThisType) { + writeKeyword(writer, SyntaxKind.ThisKeyword); + writePunctuation(writer, SyntaxKind.ColonToken); + writeSpace(writer); + buildTypeDisplay(thisType, writer, enclosingDeclaration, flags, symbolStack); + } for (let i = 0; i < parameters.length; i++) { - if (i > 0) { + if (i > 0 || useThisType) { writePunctuation(writer, SyntaxKind.CommaToken); writeSpace(writer); } @@ -2247,7 +2254,7 @@ namespace ts { buildDisplayForTypeParametersAndDelimiters(signature.typeParameters, writer, enclosingDeclaration, flags, symbolStack); } - buildDisplayForParametersAndDelimiters(signature.parameters, writer, enclosingDeclaration, flags, symbolStack); + buildDisplayForParametersAndDelimiters(signature.thisType, signature.parameters, writer, enclosingDeclaration, flags, symbolStack); buildReturnTypeDisplay(signature, writer, enclosingDeclaration, flags, symbolStack); } @@ -3414,7 +3421,7 @@ namespace ts { // Returns true if the class or interface member given by the symbol is free of "this" references. The // function may return false for symbols that are actually free of "this" references because it is not // feasible to perform a complete analysis in all cases. In particular, property members with types - // inferred from their initializers and function members with inferred return types are convervatively + // inferred from their initializers and function members with inferred return types are conservatively // assumed not to be free of "this" references. function isIndependentMember(symbol: Symbol): boolean { if (symbol.declarations && symbol.declarations.length === 1) { @@ -3426,6 +3433,7 @@ namespace ts { return isIndependentVariableLikeDeclaration(declaration); case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: + return compilerOptions.strictThis ? false : isIndependentFunctionLikeDeclaration(declaration); case SyntaxKind.Constructor: return isIndependentFunctionLikeDeclaration(declaration); } @@ -3525,12 +3533,13 @@ namespace ts { resolveObjectTypeMembers(type, source, typeParameters, typeArguments); } - function createSignature(declaration: SignatureDeclaration, typeParameters: TypeParameter[], parameters: Symbol[], + function createSignature(declaration: SignatureDeclaration, typeParameters: TypeParameter[], parameters: Symbol[], thisType: Type, resolvedReturnType: Type, minArgumentCount: number, hasRestParameter: boolean, hasStringLiterals: boolean): Signature { const sig = new Signature(checker); sig.declaration = declaration; sig.typeParameters = typeParameters; sig.parameters = parameters; + sig.thisType = thisType; sig.resolvedReturnType = resolvedReturnType; sig.minArgumentCount = minArgumentCount; sig.hasRestParameter = hasRestParameter; @@ -3539,15 +3548,19 @@ namespace ts { } function cloneSignature(sig: Signature): Signature { - return createSignature(sig.declaration, sig.typeParameters, sig.parameters, sig.resolvedReturnType, + return createSignature(sig.declaration, sig.typeParameters, sig.parameters, sig.thisType, sig.resolvedReturnType, sig.minArgumentCount, sig.hasRestParameter, sig.hasStringLiterals); } + function getParameterTypeAtIndex(signature: Signature, i: number, max: number, outOfRangeType?: Type): Type { + return i < max ? getTypeOfSymbol(signature.parameters[i]) : (outOfRangeType || getRestTypeOfSignature(signature)); + } + function getDefaultConstructSignatures(classType: InterfaceType): Signature[] { const baseConstructorType = getBaseConstructorTypeOfClass(classType); const baseSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct); if (baseSignatures.length === 0) { - return [createSignature(undefined, classType.localTypeParameters, emptyArray, classType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)]; + return [createSignature(undefined, classType.localTypeParameters, emptyArray, undefined, classType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)]; } const baseTypeNode = getBaseTypeNodeOfClass(classType); const typeArguments = map(baseTypeNode.typeArguments, getTypeFromTypeNode); @@ -4077,6 +4090,7 @@ namespace ts { const parameters: Symbol[] = []; let hasStringLiterals = false; let minArgumentCount = -1; + let thisType: Type = undefined; const isJSConstructSignature = isJSDocConstructSignature(declaration); let returnType: Type = undefined; @@ -4092,15 +4106,23 @@ namespace ts { const resolvedSymbol = resolveName(param, paramSymbol.name, SymbolFlags.Value, undefined, undefined); paramSymbol = resolvedSymbol; } - parameters.push(paramSymbol); - + if (paramSymbol.name === "this") { + thisType = param.type && getTypeOfSymbol(paramSymbol); + if (i !== 0 || declaration.kind === SyntaxKind.Constructor) { + error(param, Diagnostics.this_cannot_be_referenced_in_current_location); + } + } + else { + parameters.push(paramSymbol); + } + if (param.type && param.type.kind === SyntaxKind.StringLiteralType) { hasStringLiterals = true; } if (param.initializer || param.questionToken || param.dotDotDotToken) { if (minArgumentCount < 0) { - minArgumentCount = i; + minArgumentCount = i - (thisType ? 1 : 0); } } else { @@ -4110,7 +4132,22 @@ namespace ts { } if (minArgumentCount < 0) { - minArgumentCount = declaration.parameters.length; + minArgumentCount = declaration.parameters.length - (thisType ? 1 : 0); + } + if (!thisType && compilerOptions.strictThis) { + if (declaration.kind === SyntaxKind.FunctionDeclaration + || declaration.kind === SyntaxKind.CallSignature + || declaration.kind == SyntaxKind.FunctionExpression + || declaration.kind === SyntaxKind.FunctionType) { + thisType = voidType; + } + else if ((declaration.kind === SyntaxKind.MethodDeclaration || declaration.kind === SyntaxKind.MethodSignature) + && (isClassLike(declaration.parent) || declaration.parent.kind === SyntaxKind.InterfaceDeclaration)) { + thisType = declaration.flags & NodeFlags.Static ? + getWidenedType(checkExpression((declaration.parent).name)) : + getThisType(declaration.name); + Debug.assert(!!thisType, "couldn't find implicit this type"); + } } if (isJSConstructSignature) { @@ -4143,7 +4180,7 @@ namespace ts { } } - links.resolvedSignature = createSignature(declaration, typeParameters, parameters, returnType, minArgumentCount, hasRestParameter(declaration), hasStringLiterals); + links.resolvedSignature = createSignature(declaration, typeParameters, parameters, thisType, returnType, minArgumentCount, hasRestParameter(declaration), hasStringLiterals); } return links.resolvedSignature; } @@ -4834,7 +4871,7 @@ namespace ts { return links.resolvedType; } - function getThisType(node: TypeNode): Type { + function getThisType(node: Node): Type { const container = getThisContainer(node, /*includeArrowFunctions*/ false); const parent = container && container.parent; if (parent && (isClassLike(parent) || parent.kind === SyntaxKind.InterfaceDeclaration)) { @@ -5062,6 +5099,7 @@ namespace ts { } const result = createSignature(signature.declaration, freshTypeParameters, instantiateList(signature.parameters, mapper, instantiateSymbol), + signature.thisType ? instantiateType(signature.thisType, mapper) : undefined, instantiateType(signature.resolvedReturnType, mapper), signature.minArgumentCount, signature.hasRestParameter, signature.hasStringLiterals); result.target = signature; @@ -5175,7 +5213,14 @@ namespace ts { } function isContextSensitiveFunctionLikeDeclaration(node: FunctionLikeDeclaration) { - return !node.typeParameters && node.parameters.length && !forEach(node.parameters, p => p.type); + if (compilerOptions.strictThis) { + return !node.typeParameters && + (!forEach(node.parameters, p => p.type) + || (node.kind !== SyntaxKind.ArrowFunction && (!node.parameters.length || (node.parameters[0].name).text !== "this"))); + } + else { + return !node.typeParameters && node.parameters.length && !forEach(node.parameters, p => p.type); + } } function getTypeWithoutSignatures(type: Type): Type { @@ -5252,6 +5297,22 @@ namespace ts { target = getErasedSignature(target); let result = Ternary.True; + if (source.thisType || target.thisType) { + const s = source.thisType || anyType; + const t = target.thisType || anyType; + if (s !== voidType) { + // void sources are assignable to anything. + let related = compareTypes(getApparentType(t), getApparentType(s), reportErrors); + if (!related) { + related = compareTypes(getApparentType(s), getApparentType(t), /*reportErrors*/ false); + if (!related) { + errorReporter(Diagnostics.Types_of_parameters_0_and_1_are_incompatible, "this", "this"); + return Ternary.False; + } + } + result &= related; + } + } const sourceMax = getNumNonRestParameters(source); const targetMax = getNumNonRestParameters(target); @@ -6434,9 +6495,7 @@ namespace ts { count = sourceMax < targetMax ? sourceMax : targetMax; } for (let i = 0; i < count; i++) { - const s = i < sourceMax ? getTypeOfSymbol(source.parameters[i]) : getRestTypeOfSignature(source); - const t = i < targetMax ? getTypeOfSymbol(target.parameters[i]) : getRestTypeOfSignature(target); - callback(s, t); + callback(getParameterTypeAtIndex(source, i, sourceMax), getParameterTypeAtIndex(target, i, targetMax)); } } @@ -7313,7 +7372,12 @@ namespace ts { if (needToCaptureLexicalThis) { captureLexicalThis(node, container); } - + if (isFunctionLike(container)) { + const signature = getSignatureFromDeclaration(container); + if (signature.thisType) { + return signature.thisType; + } + } if (isClassLike(container.parent)) { const symbol = getSymbolOfNode(container.parent); return container.flags & NodeFlags.Static ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol)).thisType; @@ -7330,7 +7394,7 @@ namespace ts { if (container.kind === SyntaxKind.FunctionExpression) { if (getSpecialPropertyAssignmentKind(container.parent) === SpecialPropertyAssignmentKind.PrototypeProperty) { // Get the 'x' of 'x.prototype.y = f' (here, 'f' is 'container') - const className = (((container.parent as BinaryExpression) // x.protoype.y = f + const className = (((container.parent as BinaryExpression) // x.prototype.y = f .left as PropertyAccessExpression) // x.prototype.y .expression as PropertyAccessExpression) // x.prototype .expression; // x @@ -9306,7 +9370,7 @@ namespace ts { return getSignatureInstantiation(signature, getInferredTypes(context)); } - function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: Expression[], excludeArgument: boolean[], context: InferenceContext): void { + function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: Expression[], excludeCallee: boolean, excludeArgument: boolean[], context: InferenceContext): void { const typeParameters = signature.typeParameters; const inferenceMapper = getInferenceMapper(context); @@ -9332,6 +9396,13 @@ namespace ts { context.failedTypeParameterIndex = undefined; } + const calleeNode = node.kind === SyntaxKind.CallExpression && ((node).expression).expression; + if (signature.thisType) { + const mapper = excludeCallee !== undefined ? identityMapper : inferenceMapper; + const calleeType: Type = calleeNode ? checkExpressionWithContextualType(calleeNode, signature.thisType, mapper) : voidType; + inferTypes(context, calleeType, signature.thisType); + } + // We perform two passes over the arguments. In the first pass we infer from all arguments, but use // wildcards for all context sensitive function expressions. const argCount = getEffectiveArgumentCount(node, args, signature); @@ -9361,8 +9432,13 @@ namespace ts { // Decorators will not have `excludeArgument`, as their arguments cannot be contextually typed. // Tagged template expressions will always have `undefined` for `excludeArgument[0]`. if (excludeArgument) { + if (signature.thisType && calleeNode) { + if (excludeCallee === false) { + inferTypes(context, checkExpressionWithContextualType(calleeNode, signature.thisType, inferenceMapper), signature.thisType); + } + } for (let i = 0; i < argCount; i++) { - // No need to check for omitted args and template expressions, their exlusion value is always undefined + // No need to check for omitted args and template expressions, their exclusion value is always undefined if (excludeArgument[i] === false) { const arg = args[i]; const paramType = getTypeAtPosition(signature, i); @@ -9405,6 +9481,18 @@ namespace ts { } function checkApplicableSignature(node: CallLikeExpression, args: Expression[], signature: Signature, relation: Map, excludeArgument: boolean[], reportErrors: boolean) { + const headMessage = Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1; + if (signature.thisType && signature.thisType !== voidType && node.kind !== SyntaxKind.NewExpression) { + // If the source is not of the form `x.f`, then sourceType = voidType + // If the target is voidType, then the check is skipped -- anything is compatible. + // If the the expression is a new expression, then the check is skipped. + const calleeNode = node.kind === SyntaxKind.CallExpression && ((node).expression).expression; + const calleeType: Type = calleeNode ? checkExpressionWithContextualType(calleeNode, signature.thisType, undefined) : voidType; + const errorNode = reportErrors ? (calleeNode || node) : undefined; + if (!checkTypeRelatedTo(calleeType, getApparentType(signature.thisType), relation, errorNode, headMessage)) { + return false; + } + } const argCount = getEffectiveArgumentCount(node, args, signature); for (let i = 0; i < argCount; i++) { const arg = getEffectiveArgument(node, args, i); @@ -9424,7 +9512,6 @@ namespace ts { // Use argument expression as error location when reporting errors const errorNode = reportErrors ? getEffectiveArgumentErrorNode(node, i, arg) : undefined; - const headMessage = Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1; if (!checkTypeRelatedTo(argType, paramType, relation, errorNode, headMessage)) { return false; } @@ -9778,8 +9865,13 @@ namespace ts { // // For a decorator, no arguments are susceptible to contextual typing due to the fact // decorators are applied to a declaration by the emitter, and not to an expression. + let excludeCallee: boolean; let excludeArgument: boolean[]; if (!isDecorator) { + const calleeNode = node.kind === SyntaxKind.CallExpression && ((node).expression).expression; + if (calleeNode && isContextSensitive(calleeNode)) { + excludeCallee = true; + } // We do not need to call `getEffectiveArgumentCount` here as it only // applies when calculating the number of arguments for a decorator. for (let i = isTaggedTemplate ? 1 : 0; i < args.length; i++) { @@ -9928,7 +10020,7 @@ namespace ts { typeArgumentsAreValid = checkTypeArguments(candidate, typeArguments, typeArgumentTypes, /*reportErrors*/ false); } else { - inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); + inferTypeArguments(node, candidate, args, excludeCallee, excludeArgument, inferenceContext); typeArgumentsAreValid = inferenceContext.failedTypeParameterIndex === undefined; typeArgumentTypes = inferenceContext.inferredTypes; } @@ -10086,13 +10178,16 @@ namespace ts { // If expressionType's apparent type is an object type with no construct signatures but // one or more call signatures, the expression is processed as a function call. A compile-time // error occurs if the result of the function call is not Void. The type of the result of the - // operation is Any. + // operation is the function's this type. It is an error to have a Void this type. const callSignatures = getSignaturesOfType(expressionType, SignatureKind.Call); if (callSignatures.length) { const signature = resolveCall(node, callSignatures, candidatesOutArray); if (getReturnTypeOfSignature(signature) !== voidType) { error(node, Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword); } + if (signature.thisType === voidType) { + error(node, Diagnostics.A_function_that_is_called_with_the_new_keyword_cannot_have_a_this_type_that_is_void); + } return signature; } @@ -10244,10 +10339,10 @@ namespace ts { if (funcSymbol && funcSymbol.members && (funcSymbol.flags & SymbolFlags.Function)) { return getInferredClassType(funcSymbol); } - else if (compilerOptions.noImplicitAny) { + else if (compilerOptions.noImplicitAny && !signature.thisType) { error(node, Diagnostics.new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type); } - return anyType; + return signature.thisType || anyType; } } @@ -10282,11 +10377,17 @@ namespace ts { function getTypeAtPosition(signature: Signature, pos: number): Type { return signature.hasRestParameter ? - pos < signature.parameters.length - 1 ? getTypeOfSymbol(signature.parameters[pos]) : getRestTypeOfSignature(signature) : - pos < signature.parameters.length ? getTypeOfSymbol(signature.parameters[pos]) : anyType; + getParameterTypeAtIndex(signature, pos, signature.parameters.length - 1) : + getParameterTypeAtIndex(signature, pos, signature.parameters.length, anyType); } function assignContextualParameterTypes(signature: Signature, context: Signature, mapper: TypeMapper) { + if (context.thisType) { + if (signature.declaration.kind !== SyntaxKind.ArrowFunction) { + // do not contextually type thisType for ArrowFunction. + signature.thisType = context.thisType; + } + } const len = signature.parameters.length - (signature.hasRestParameter ? 1 : 0); for (let i = 0; i < len; i++) { const parameter = signature.parameters[i]; From a639b71ed0837775593240a1a86cc14594f3213b Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 29 Jan 2016 14:34:44 -0800 Subject: [PATCH 024/274] Skip emit of this types as first parameter. --- src/compiler/emitter.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 4d771bd2538..fc8e811fb65 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -4436,8 +4436,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge write("("); if (node) { const parameters = node.parameters; + const skipCount = node.parameters.length && (node.parameters[0].name).text === "this" ? 1 : 0; const omitCount = languageVersion < ScriptTarget.ES6 && hasRestParameter(node) ? 1 : 0; - emitList(parameters, 0, parameters.length - omitCount, /*multiLine*/ false, /*trailingComma*/ false); + emitList(parameters, skipCount, parameters.length - omitCount - skipCount, /*multiLine*/ false, /*trailingComma*/ false); } write(")"); decreaseIndent(); From 9bd7afb143fff13458a514da29bd7ad8547a4d68 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 29 Jan 2016 14:39:01 -0800 Subject: [PATCH 025/274] Add new error message and strictThis flag --- src/compiler/commandLineParser.ts | 4 ++++ src/compiler/diagnosticMessages.json | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index d5bf95a6405..3eb42292fb1 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -130,6 +130,10 @@ namespace ts { name: "skipDefaultLibCheck", type: "boolean", }, + { + name: "strictThis", + type: "boolean", + }, { name: "out", type: "string", diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index ca5a6d9d415..2043a89c8fd 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1819,6 +1819,10 @@ "category": "Error", "code": 2670 }, + "A function that is called with the 'new' keyword cannot have a 'this' type that is void.": { + "category": "Error", + "code": 2671 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", "code": 4000 From ca162090325e35fe8479d90698b35b2d89360f7f Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 29 Jan 2016 14:43:50 -0800 Subject: [PATCH 026/274] Make compiler strictThis clean. --- src/compiler/core.ts | 19 ++++++----- src/compiler/program.ts | 3 +- src/compiler/sourcemap.ts | 8 ++--- src/compiler/sys.ts | 2 +- src/compiler/types.ts | 18 +++++----- src/compiler/utilities.ts | 20 +++++------ src/harness/harness.ts | 32 ++++++++--------- src/harness/loggedIO.ts | 34 ++++++++++--------- src/server/editorServices.ts | 2 +- src/server/node.d.ts | 4 +-- .../formatting/ruleOperationContext.ts | 4 +-- src/services/utilities.ts | 2 +- 12 files changed, 77 insertions(+), 71 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 21536da36ff..ab8de44ec98 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -818,25 +818,26 @@ namespace ts { getSignatureConstructor(): new (checker: TypeChecker) => Signature; } + // TODO: Add a 'this' parameter after I update the previous-version compiler function Symbol(flags: SymbolFlags, name: string) { - this.flags = flags; - this.name = name; - this.declarations = undefined; + (this).flags = flags; + (this).name = name; + (this).declarations = undefined; } function Type(checker: TypeChecker, flags: TypeFlags) { - this.flags = flags; + (this).flags = flags; } function Signature(checker: TypeChecker) { } function Node(kind: SyntaxKind, pos: number, end: number) { - this.kind = kind; - this.pos = pos; - this.end = end; - this.flags = NodeFlags.None; - this.parent = undefined; + (this).kind = kind; + (this).pos = pos; + (this).end = end; + (this).flags = NodeFlags.None; + (this).parent = undefined; } export let objectAllocator: ObjectAllocator = { diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 803ae47b0fd..88c77aa5759 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -933,8 +933,9 @@ namespace ts { return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = createTypeChecker(program, /*produceDiagnostics:*/ false)); } + // TODO: needs to have this: Program function emit(sourceFile?: SourceFile, writeFileCallback?: WriteFileCallback, cancellationToken?: CancellationToken): EmitResult { - return runWithCancellationToken(() => emitWorker(this, sourceFile, writeFileCallback, cancellationToken)); + return runWithCancellationToken(() => emitWorker((this), sourceFile, writeFileCallback, cancellationToken)); } function isEmitBlocked(emitFileName: string): boolean { diff --git a/src/compiler/sourcemap.ts b/src/compiler/sourcemap.ts index 8abf1432b0c..fb61f8b78b8 100644 --- a/src/compiler/sourcemap.ts +++ b/src/compiler/sourcemap.ts @@ -4,10 +4,10 @@ namespace ts { export interface SourceMapWriter { getSourceMapData(): SourceMapData; - setSourceFile(sourceFile: SourceFile): void; - emitPos(pos: number): void; - emitStart(range: TextRange): void; - emitEnd(range: TextRange, stopOverridingSpan?: boolean): void; + setSourceFile: (sourceFile: SourceFile) => void; + emitPos: (pos: number) => void; + emitStart: (range: TextRange) => void; + emitEnd: (range: TextRange, stopOverridingSpan?: boolean) => void; changeEmitSourcePos(): void; getText(): string; getSourceMappingURL(): string; diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index bf25d39aa43..1a9da39bf9a 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -63,7 +63,7 @@ namespace ts { useCaseSensitiveFileNames?: boolean; echo(s: string): void; quit(exitCode?: number): void; - fileExists(path: string): boolean; + fileExists: (path: string) => boolean; directoryExists(path: string): boolean; createDirectory(path: string): void; resolvePath(path: string): string; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 796529d9d4f..9c2612d96b6 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1593,8 +1593,8 @@ namespace ts { } export interface ScriptReferenceHost { - getCompilerOptions(): CompilerOptions; - getSourceFile(fileName: string): SourceFile; + getCompilerOptions: () => CompilerOptions; + getSourceFile: (fileName: string) => SourceFile; getCurrentDirectory(): string; } @@ -1625,7 +1625,7 @@ namespace ts { /** * Get a list of files in the program */ - getSourceFiles(): SourceFile[]; + getSourceFiles: () => SourceFile[]; /** * Emits the JavaScript and declaration files. If targetSourceFile is not specified, then @@ -1650,7 +1650,7 @@ namespace ts { */ getTypeChecker(): TypeChecker; - /* @internal */ getCommonSourceDirectory(): string; + /* @internal */ getCommonSourceDirectory: () => string; // For testing purposes only. Should not be used by any other consumers (including the // language service). @@ -1781,7 +1781,7 @@ namespace ts { buildParameterDisplay(parameter: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaraiton?: Node, flags?: TypeFormatFlags): void; - buildDisplayForParametersAndDelimiters(parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + buildDisplayForParametersAndDelimiters(thisType: Type, parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; } @@ -1905,11 +1905,11 @@ namespace ts { getReferencedImportDeclaration(node: Identifier): Declaration; getReferencedDeclarationWithCollidingName(node: Identifier): Declaration; isDeclarationWithCollidingName(node: Declaration): boolean; - isValueAliasDeclaration(node: Node): boolean; - isReferencedAliasDeclaration(node: Node, checkChildren?: boolean): boolean; + isValueAliasDeclaration: (node: Node) => boolean; + isReferencedAliasDeclaration: (node: Node, checkChildren?: boolean) => boolean; isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean; getNodeCheckFlags(node: Node): NodeCheckFlags; - isDeclarationVisible(node: Declaration): boolean; + isDeclarationVisible: (node: Declaration) => boolean; collectLinkedAliases(node: Identifier): Node[]; isImplementationOfOverload(node: FunctionLikeDeclaration): boolean; writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; @@ -2279,6 +2279,7 @@ namespace ts { declaration: SignatureDeclaration; // Originating declaration typeParameters: TypeParameter[]; // Type parameters (undefined if non-generic) parameters: Symbol[]; // Parameters + thisType?: Type; // type of this-type /* @internal */ resolvedReturnType: Type; // Resolved return type /* @internal */ @@ -2429,6 +2430,7 @@ namespace ts { rootDir?: string; sourceMap?: boolean; sourceRoot?: string; + strictThis?: boolean, suppressExcessPropertyErrors?: boolean; suppressImplicitAnyIndexErrors?: boolean; target?: ScriptTarget; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index bab66eb0688..bce821c3756 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -32,11 +32,11 @@ namespace ts { } export interface EmitHost extends ScriptReferenceHost { - getSourceFiles(): SourceFile[]; + getSourceFiles: () => SourceFile[]; - getCommonSourceDirectory(): string; - getCanonicalFileName(fileName: string): string; - getNewLine(): string; + getCommonSourceDirectory: () => string; + getCanonicalFileName: (fileName: string) => string; + getNewLine: () => string; isEmitBlocked(emitFileName: string): boolean; @@ -1869,11 +1869,11 @@ namespace ts { } export interface EmitTextWriter { - write(s: string): void; - writeTextOfNode(text: string, node: Node): void; - writeLine(): void; - increaseIndent(): void; - decreaseIndent(): void; + write: (s: string) => void; + writeTextOfNode: (text: string, node: Node) => void; + writeLine: () => void; + increaseIndent: () => void; + decreaseIndent: () => void; getText(): string; rawWrite(s: string): void; writeLiteral(s: string): void; @@ -2490,7 +2490,7 @@ namespace ts { * as the fallback implementation does not check for circular references by default. */ export const stringify: (value: any) => string = typeof JSON !== "undefined" && JSON.stringify - ? JSON.stringify + ? JSON.stringify : stringifyFallback; /** diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 2b0c95c0a61..3b211a0d91a 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -417,24 +417,24 @@ namespace Harness.Path { namespace Harness { export interface IO { - newLine(): string; - getCurrentDirectory(): string; - useCaseSensitiveFileNames(): boolean; - resolvePath(path: string): string; - readFile(path: string): string; - writeFile(path: string, contents: string): void; - directoryName(path: string): string; - createDirectory(path: string): void; - fileExists(fileName: string): boolean; - directoryExists(path: string): boolean; - deleteFile(fileName: string): void; - listFiles(path: string, filter: RegExp, options?: { recursive?: boolean }): string[]; - log(text: string): void; - getMemoryUsage?(): number; args(): string[]; - getExecutingFilePath(): string; - exit(exitCode?: number): void; + newLine(): string; + readFile(this: ts.System | IO, path: string): string; + writeFile(path: string, contents: string): void; + resolvePath(path: string): string; + fileExists: (fileName: string) => boolean; + directoryExists: (path: string) => boolean; + createDirectory(path: string): void; + getExecutingFilePath(this: ts.System | IO): string; + getCurrentDirectory(): string; readDirectory(path: string, extension?: string, exclude?: string[]): string[]; + getMemoryUsage?(): number; + exit(exitCode?: number): void; + deleteFile(fileName: string): void; + directoryName: (path: string) => string; + listFiles(path: string, filter: RegExp, options?: { recursive?: boolean }): string[]; + log: (text: string) => void; + useCaseSensitiveFileNames(): boolean; } export var IO: IO; diff --git a/src/harness/loggedIO.ts b/src/harness/loggedIO.ts index 3d51682f745..dbc05112f3e 100644 --- a/src/harness/loggedIO.ts +++ b/src/harness/loggedIO.ts @@ -70,11 +70,11 @@ interface IOLog { interface PlaybackControl { startReplayFromFile(logFileName: string): void; - startReplayFromString(logContents: string): void; - startReplayFromData(log: IOLog): void; + startReplayFromString(this: PlaybackControl, logContents: string): void; + startReplayFromData(this: PlaybackControl, log: IOLog): void; endReplay(): void; startRecord(logFileName: string): void; - endRecord(): void; + endRecord(this: PlaybackControl): void; } namespace Playback { @@ -127,6 +127,8 @@ namespace Playback { function initWrapper(wrapper: PlaybackSystem, underlying: ts.System): void; function initWrapper(wrapper: PlaybackIO, underlying: Harness.IO): void; function initWrapper(wrapper: PlaybackSystem | PlaybackIO, underlying: ts.System | Harness.IO): void { + // TODO: Define a common interface over ts.System | Harness.IO and stop passing a union type. + const underlyingShim: any = underlying; ts.forEach(Object.keys(underlying), prop => { (wrapper)[prop] = (underlying)[prop]; }); @@ -154,20 +156,20 @@ namespace Playback { }; wrapper.startReplayFromFile = logFn => { - wrapper.startReplayFromString(underlying.readFile(logFn)); + wrapper.startReplayFromString(underlyingShim.readFile(logFn)); }; wrapper.endRecord = () => { if (recordLog !== undefined) { let i = 0; const fn = () => recordLogFileNameBase + i + ".json"; - while (underlying.fileExists(fn())) i++; - underlying.writeFile(fn(), JSON.stringify(recordLog)); + while (underlyingShim.fileExists(fn())) i++; + underlyingShim.writeFile(fn(), JSON.stringify(recordLog)); recordLog = undefined; } }; wrapper.fileExists = recordReplay(wrapper.fileExists, underlying)( - path => callAndRecord(underlying.fileExists(path), recordLog.fileExists, { path }), + path => callAndRecord(underlyingShim.fileExists(path), recordLog.fileExists, { path }), memoize(path => { // If we read from the file, it must exist if (findResultByPath(wrapper, replayLog.filesRead, path, null) !== null) { @@ -184,10 +186,10 @@ namespace Playback { return replayLog.executingPath; } else if (recordLog !== undefined) { - return recordLog.executingPath = underlying.getExecutingFilePath(); + return recordLog.executingPath = underlyingShim.getExecutingFilePath(); } else { - return underlying.getExecutingFilePath(); + return underlyingShim.getExecutingFilePath(); } }; @@ -196,20 +198,20 @@ namespace Playback { return replayLog.currentDirectory || ""; } else if (recordLog !== undefined) { - return recordLog.currentDirectory = underlying.getCurrentDirectory(); + return recordLog.currentDirectory = underlyingShim.getCurrentDirectory(); } else { - return underlying.getCurrentDirectory(); + return underlyingShim.getCurrentDirectory(); } }; wrapper.resolvePath = recordReplay(wrapper.resolvePath, underlying)( - path => callAndRecord(underlying.resolvePath(path), recordLog.pathsResolved, { path }), + path => callAndRecord(underlyingShim.resolvePath(path), recordLog.pathsResolved, { path }), memoize(path => findResultByFields(replayLog.pathsResolved, { path }, !ts.isRootedDiskPath(ts.normalizeSlashes(path)) && replayLog.currentDirectory ? replayLog.currentDirectory + "/" + path : ts.normalizeSlashes(path)))); wrapper.readFile = recordReplay(wrapper.readFile, underlying)( path => { - const result = underlying.readFile(path); + const result = underlyingShim.readFile(path); const logEntry = { path, codepage: 0, result: { contents: result, codepage: 0 } }; recordLog.filesRead.push(logEntry); return result; @@ -226,14 +228,14 @@ namespace Playback { (path, extension, exclude) => findResultByPath(wrapper, replayLog.directoriesRead.filter(d => d.extension === extension && ts.arrayIsEqualTo(d.exclude, exclude)), path)); wrapper.writeFile = recordReplay(wrapper.writeFile, underlying)( - (path, contents) => callAndRecord(underlying.writeFile(path, contents), recordLog.filesWritten, { path, contents, bom: false }), - (path, contents) => noOpReplay("writeFile")); + (path: string, contents: string) => callAndRecord(underlyingShim.writeFile(path, contents), recordLog.filesWritten, { path, contents, bom: false }), + (path: string, contents: string) => noOpReplay("writeFile")); wrapper.exit = (exitCode) => { if (recordLog !== undefined) { wrapper.endRecord(); } - underlying.exit(exitCode); + underlyingShim.exit(exitCode); }; } diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index e2ec5cc159f..5516b18e0de 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1834,7 +1834,7 @@ namespace ts.server { if (!rangeEnd) { rangeEnd = this.root.charCount(); } - const walkFns = { + const walkFns: ILineIndexWalker = { goSubtree: true, done: false, leaf: function (relativeStart: number, relativeLength: number, ll: LineLeaf) { diff --git a/src/server/node.d.ts b/src/server/node.d.ts index 0bde0bb6602..8e4d8c28e9b 100644 --- a/src/server/node.d.ts +++ b/src/server/node.d.ts @@ -68,7 +68,7 @@ interface BufferConstructor { new (array: any[]): Buffer; prototype: Buffer; isBuffer(obj: any): boolean; - byteLength(string: string, encoding?: string): number; + byteLength: (string: string, encoding?: string) => number; concat(list: Buffer[], totalLength?: number): Buffer; } declare var Buffer: BufferConstructor; @@ -190,7 +190,7 @@ declare namespace NodeJS { nextTick(callback: Function): void; umask(mask?: number): number; uptime(): number; - hrtime(time?: number[]): number[]; + hrtime: (time?: number[]) => number[]; // Worker send? (message: any, sendHandle?: any): void; diff --git a/src/services/formatting/ruleOperationContext.ts b/src/services/formatting/ruleOperationContext.ts index 47330faa0dd..3108095e8e6 100644 --- a/src/services/formatting/ruleOperationContext.ts +++ b/src/services/formatting/ruleOperationContext.ts @@ -6,8 +6,8 @@ namespace ts.formatting { export class RuleOperationContext { private customContextChecks: { (context: FormattingContext): boolean; }[]; - constructor(...funcs: { (context: FormattingContext): boolean; }[]) { - this.customContextChecks = funcs; + constructor(...funcs: { (this: typeof Rules, context: FormattingContext): boolean; }[]) { + this.customContextChecks = <{ (this: any, context: FormattingContext): boolean }[]>funcs; } static Any: RuleOperationContext = new RuleOperationContext(); diff --git a/src/services/utilities.ts b/src/services/utilities.ts index afdc85fffd8..0363e45a64a 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -769,7 +769,7 @@ namespace ts { * The default is CRLF. */ export function getNewLineOrDefaultFromHost(host: LanguageServiceHost | LanguageServiceShimHost) { - return host.getNewLine ? host.getNewLine() : carriageReturnLineFeed; + return (host).getNewLine ? (host).getNewLine() : carriageReturnLineFeed; } export function lineBreakPart() { From 22e571f1e9a0250e406734f479d0f1a91fca4347 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 29 Jan 2016 14:44:20 -0800 Subject: [PATCH 027/274] Add services support for this types. --- src/services/services.ts | 27 ++++++++++++++++++++------- src/services/signatureHelp.ts | 2 +- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index cb57d415c66..1a43f9a744b 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -19,15 +19,15 @@ namespace ts { getChildCount(sourceFile?: SourceFile): number; getChildAt(index: number, sourceFile?: SourceFile): Node; getChildren(sourceFile?: SourceFile): Node[]; - getStart(sourceFile?: SourceFile): number; + getStart(this: Node, sourceFile?: SourceFile): number; getFullStart(): number; - getEnd(): number; + getEnd(this: Node): number; getWidth(sourceFile?: SourceFile): number; getFullWidth(): number; getLeadingTriviaWidth(sourceFile?: SourceFile): number; getFullText(sourceFile?: SourceFile): string; getText(sourceFile?: SourceFile): string; - getFirstToken(sourceFile?: SourceFile): Node; + getFirstToken(this: Node, sourceFile?: SourceFile): Node; getLastToken(sourceFile?: SourceFile): Node; } @@ -740,6 +740,7 @@ namespace ts { declaration: SignatureDeclaration; typeParameters: TypeParameter[]; parameters: Symbol[]; + thisType: Type; resolvedReturnType: Type; minArgumentCount: number; hasRestParameter: boolean; @@ -4021,6 +4022,9 @@ namespace ts { if (typeChecker.isArgumentsSymbol(symbol)) { return ScriptElementKind.localVariableElement; } + if (location.kind === SyntaxKind.ThisKeyword && isExpression(location)) { + return ScriptElementKind.parameterElement; + } if (flags & SymbolFlags.Variable) { if (isFirstDeclarationOfSymbolParameter(symbol)) { return ScriptElementKind.parameterElement; @@ -4083,6 +4087,7 @@ namespace ts { const symbolFlags = symbol.flags; let symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, symbolFlags, location); let hasAddedSymbolInfo: boolean; + const isThisExpression: boolean = location.kind === SyntaxKind.ThisKeyword && isExpression(location); let type: Type; // Class at constructor site need to be shown as constructor apart from property,method, vars @@ -4093,7 +4098,7 @@ namespace ts { } let signature: Signature; - type = typeChecker.getTypeOfSymbolAtLocation(symbol, location); + type = isThisExpression ? typeChecker.getTypeAtLocation(location) : typeChecker.getTypeOfSymbolAtLocation(symbol, location); if (type) { if (location.parent && location.parent.kind === SyntaxKind.PropertyAccessExpression) { const right = (location.parent).name; @@ -4204,7 +4209,7 @@ namespace ts { } } } - if (symbolFlags & SymbolFlags.Class && !hasAddedSymbolInfo) { + if (symbolFlags & SymbolFlags.Class && !hasAddedSymbolInfo && !isThisExpression) { if (getDeclarationOfKind(symbol, SyntaxKind.ClassExpression)) { // Special case for class expressions because we would like to indicate that // the class name is local to the class body (similar to function expression) @@ -4346,11 +4351,19 @@ namespace ts { if (!hasAddedSymbolInfo) { if (symbolKind !== ScriptElementKind.unknown) { if (type) { - addPrefixForAnyFunctionOrVar(symbol, symbolKind); + if (isThisExpression) { + addNewLineIfDisplayPartsExist(); + displayParts.push(keywordPart(SyntaxKind.ThisKeyword)); + } + else { + addPrefixForAnyFunctionOrVar(symbol, symbolKind); + } + // For properties, variables and local vars: show the type if (symbolKind === ScriptElementKind.memberVariableElement || symbolFlags & SymbolFlags.Variable || - symbolKind === ScriptElementKind.localVariableElement) { + symbolKind === ScriptElementKind.localVariableElement || + isThisExpression) { displayParts.push(punctuationPart(SyntaxKind.ColonToken)); displayParts.push(spacePart()); // If the type is type parameter, format it specially diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index 02e36e185a5..cdf0b997bcc 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -559,7 +559,7 @@ namespace ts.SignatureHelp { signatureHelpParameters = typeParameters && typeParameters.length > 0 ? map(typeParameters, createSignatureHelpParameterForTypeParameter) : emptyArray; suffixDisplayParts.push(punctuationPart(SyntaxKind.GreaterThanToken)); let parameterParts = mapToDisplayParts(writer => - typeChecker.getSymbolDisplayBuilder().buildDisplayForParametersAndDelimiters(candidateSignature.parameters, writer, invocation)); + typeChecker.getSymbolDisplayBuilder().buildDisplayForParametersAndDelimiters(candidateSignature.thisType, candidateSignature.parameters, writer, invocation)); addRange(suffixDisplayParts, parameterParts); } else { From 5fe84781592a08b5294e01a2fbf42d1def07111d Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 29 Jan 2016 14:46:01 -0800 Subject: [PATCH 028/274] Add overloads for Function.apply/call/bind The new overloads use this types to specify the return type of these functions as well as the type of `thisArg`. --- src/lib/core.d.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/lib/core.d.ts b/src/lib/core.d.ts index 31cf0ca3136..fe2fd6b79f6 100644 --- a/src/lib/core.d.ts +++ b/src/lib/core.d.ts @@ -215,14 +215,16 @@ interface Function { * @param thisArg The object to be used as the this object. * @param argArray A set of arguments to be passed to the function. */ - apply(thisArg: any, argArray?: any): any; + apply(this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; + apply(this: Function, thisArg: any, argArray?: any): any; /** * Calls a method of an object, substituting another object for the current object. * @param thisArg The object to be used as the current object. * @param argArray A list of arguments to be passed to the method. */ - call(thisArg: any, ...argArray: any[]): any; + call(this: (this: T, ...argArray: any[]) => U, thisArg: T, ...argArray: any[]): U; + call(this: Function, thisArg: any, ...argArray: any[]): any; /** * For a given function, creates a bound function that has the same body as the original function. @@ -230,7 +232,8 @@ interface Function { * @param thisArg An object to which the this keyword can refer inside the new function. * @param argArray A list of arguments to be passed to the new function. */ - bind(thisArg: any, ...argArray: any[]): any; + bind(this: (this: T, ...argArray: any[]) => U, thisArg: T, ...argArray: any[]): (...argArray: any[]) => U; + bind(this: Function, thisArg: any, ...argArray: any[]): any; prototype: any; readonly length: number; From 04e7d811054f712276264f87a7574ba2796cd4bd Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 29 Jan 2016 14:49:52 -0800 Subject: [PATCH 029/274] Add tests and baselines for this-function types. --- .../looseThisTypeInFunctions.errors.txt | 48 + .../reference/looseThisTypeInFunctions.js | 68 ++ .../reference/thisTypeInFunctions.js | 407 +++++++ .../reference/thisTypeInFunctions.symbols | 862 ++++++++++++++ .../reference/thisTypeInFunctions.types | 1037 +++++++++++++++++ .../thisTypeInFunctionsNegative.errors.txt | 509 ++++++++ .../reference/thisTypeInFunctionsNegative.js | 386 ++++++ .../thisType/looseThisTypeInFunctions.ts | 34 + .../types/thisType/thisTypeInFunctions.ts | 209 ++++ .../thisType/thisTypeInFunctionsNegative.ts | 193 +++ .../fourslash/memberListOnExplicitThis.ts | 30 + 11 files changed, 3783 insertions(+) create mode 100644 tests/baselines/reference/looseThisTypeInFunctions.errors.txt create mode 100644 tests/baselines/reference/looseThisTypeInFunctions.js create mode 100644 tests/baselines/reference/thisTypeInFunctions.js create mode 100644 tests/baselines/reference/thisTypeInFunctions.symbols create mode 100644 tests/baselines/reference/thisTypeInFunctions.types create mode 100644 tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt create mode 100644 tests/baselines/reference/thisTypeInFunctionsNegative.js create mode 100644 tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts create mode 100644 tests/cases/conformance/types/thisType/thisTypeInFunctions.ts create mode 100644 tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts create mode 100644 tests/cases/fourslash/memberListOnExplicitThis.ts diff --git a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt new file mode 100644 index 00000000000..058a1555ed6 --- /dev/null +++ b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt @@ -0,0 +1,48 @@ +tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(20,1): error TS2322: Type '(this: C, m: number) => number' is not assignable to type '(m: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'void' is not assignable to type 'C'. +tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(27,9): error TS2345: Argument of type 'void' is not assignable to parameter of type 'I'. + + +==== tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts (2 errors) ==== + interface I { + explicitThis(this: this, m: number): number; + } + interface Unused { + implicitNoThis(m: number): number; + } + class C implements I { + n: number; + explicitThis(this: this, m: number): number { + return this.n + m; + } + implicitThis(m: number): number { + return this.n + m; + } + explicitVoid(this: void, m: number): number { + return m + 1; + } + } + let c = new C(); + c.explicitVoid = c.explicitThis; // error, 'void' is missing everything + ~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: C, m: number) => number' is not assignable to type '(m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'void' is not assignable to type 'C'. + let o = { + explicitThis: function (m) { return m }, + implicitThis(m: number): number { return m } + }; + let i: I = o; + let x = i.explicitThis; + let n = x(12); // callee:void doesn't match this:I + ~~~~~ +!!! error TS2345: Argument of type 'void' is not assignable to parameter of type 'I'. + let u: Unused; + let y = u.implicitNoThis; + n = y(12); // ok, callee:void matches this:any + c.explicitVoid = c.implicitThis // ok, implicitThis(this:any) + o.implicitThis = c.implicitThis; // ok, implicitThis(this:any) + o.implicitThis = c.explicitThis; // ok, implicitThis(this:any) is assignable to explicitThis(this: this) + o.implicitThis = i.explicitThis; + \ No newline at end of file diff --git a/tests/baselines/reference/looseThisTypeInFunctions.js b/tests/baselines/reference/looseThisTypeInFunctions.js new file mode 100644 index 00000000000..66677293c5b --- /dev/null +++ b/tests/baselines/reference/looseThisTypeInFunctions.js @@ -0,0 +1,68 @@ +//// [looseThisTypeInFunctions.ts] +interface I { + explicitThis(this: this, m: number): number; +} +interface Unused { + implicitNoThis(m: number): number; +} +class C implements I { + n: number; + explicitThis(this: this, m: number): number { + return this.n + m; + } + implicitThis(m: number): number { + return this.n + m; + } + explicitVoid(this: void, m: number): number { + return m + 1; + } +} +let c = new C(); +c.explicitVoid = c.explicitThis; // error, 'void' is missing everything +let o = { + explicitThis: function (m) { return m }, + implicitThis(m: number): number { return m } +}; +let i: I = o; +let x = i.explicitThis; +let n = x(12); // callee:void doesn't match this:I +let u: Unused; +let y = u.implicitNoThis; +n = y(12); // ok, callee:void matches this:any +c.explicitVoid = c.implicitThis // ok, implicitThis(this:any) +o.implicitThis = c.implicitThis; // ok, implicitThis(this:any) +o.implicitThis = c.explicitThis; // ok, implicitThis(this:any) is assignable to explicitThis(this: this) +o.implicitThis = i.explicitThis; + + +//// [looseThisTypeInFunctions.js] +var C = (function () { + function C() { + } + C.prototype.explicitThis = function (m) { + return this.n + m; + }; + C.prototype.implicitThis = function (m) { + return this.n + m; + }; + C.prototype.explicitVoid = function (m) { + return m + 1; + }; + return C; +}()); +var c = new C(); +c.explicitVoid = c.explicitThis; // error, 'void' is missing everything +var o = { + explicitThis: function (m) { return m; }, + implicitThis: function (m) { return m; } +}; +var i = o; +var x = i.explicitThis; +var n = x(12); // callee:void doesn't match this:I +var u; +var y = u.implicitNoThis; +n = y(12); // ok, callee:void matches this:any +c.explicitVoid = c.implicitThis; // ok, implicitThis(this:any) +o.implicitThis = c.implicitThis; // ok, implicitThis(this:any) +o.implicitThis = c.explicitThis; // ok, implicitThis(this:any) is assignable to explicitThis(this: this) +o.implicitThis = i.explicitThis; diff --git a/tests/baselines/reference/thisTypeInFunctions.js b/tests/baselines/reference/thisTypeInFunctions.js new file mode 100644 index 00000000000..0798843fc44 --- /dev/null +++ b/tests/baselines/reference/thisTypeInFunctions.js @@ -0,0 +1,407 @@ +//// [thisTypeInFunctions.ts] +// body checking +class C { + n: number; + explicitThis(this: this, m: number): number { + return this.n + m; + } + implicitThis(m: number): number { + return this.n + m; + } + explicitC(this: C, m: number): number { + return this.n + m; + } + explicitProperty(this: {n: number}, m: number): number { + return this.n + m; + } + explicitVoid(this: void, m: number): number { + return m + 1; + } +} +class D extends C { } +class B { + n: number; +} +interface I { + a: number; + explicitVoid1(this: void): number; + explicitVoid2(this: void): number; + explicitStructural(this: {a: number}): number; + explicitInterface(this: I): number; + explicitThis(this: this): number; + implicitMethod(): number; + implicitFunction: () => number; +} +function explicitStructural(this: { y: number }, x: number): number { + return x + this.y; +} +function justThis(this: { y: number }): number { + return this.y; +} +function implicitThis(n: number): number { + return 12; +} +let impl: I = { + a: 12, + explicitVoid2: () => this.a, // ok, this: any because it refers to some outer object (window?) + explicitVoid1() { return 12; }, + explicitStructural() { + return this.a; + }, + explicitInterface() { + return this.a; + }, + explicitThis() { + return this.a; + }, + implicitMethod() { + return this.a; + }, + implicitFunction: () => this.a, // ok, this: any because it refers to some outer object (window?) +} +impl.explicitVoid1 = function () { return 12; }; +impl.explicitVoid2 = () => 12; +impl.explicitStructural = function() { return this.a; }; +impl.explicitInterface = function() { return this.a; }; +impl.explicitStructural = () => 12; +impl.explicitInterface = () => 12; +impl.explicitThis = function () { return this.a; }; +impl.implicitMethod = function () { return this.a; }; +impl.implicitMethod = () => 12; +impl.implicitFunction = () => this.a; // ok, this: any because it refers to some outer object (window?) +// parameter checking +let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, f: explicitStructural }; +let implicitAnyOk: {notSpecified: number, f: (x: number) => number} = { notSpecified: 12, f: implicitThis }; +ok.f(13); +implicitThis(12); +implicitAnyOk.f(12); + +let c = new C(); +let d = new D(); +let ripped = c.explicitC; +c.explicitC(12); +c.explicitProperty(12); +c.explicitThis(12); +c.implicitThis(12); +d.explicitC(12); +d.explicitProperty(12); +d.explicitThis(12); +d.implicitThis(12); +let reconstructed: { + n: number, + explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. + implicitThis(m: number): number, + explicitC(this: C, m: number): number, + explicitProperty: (this: {n : number}, m: number) => number, + explicitVoid(this: void, m: number): number, +} = { + n: 12, + explicitThis: c.explicitThis, + implicitThis: c.implicitThis, + explicitC: c.explicitC, + explicitProperty: c.explicitProperty, + explicitVoid: c.explicitVoid +}; +reconstructed.explicitProperty(11); +reconstructed.implicitThis(11); + +// assignment checking +let unboundToSpecified: (this: { y: number }, x: number) => number = x => x + this.y; // ok, this:any +let specifiedToSpecified: (this: {y: number}, x: number) => number = explicitStructural; +let anyToSpecified: (this: { y: number }, x: number) => number = function(x: number): number { return x + 12; }; + +let unspecifiedLambda: (x: number) => number = x => x + 12; +let specifiedLambda: (this: void, x: number) => number = x => x + 12; +let unspecifiedLambdaToSpecified: (this: {y: number}, x: number) => number = unspecifiedLambda; +let specifiedLambdaToSpecified: (this: {y: number}, x: number) => number = specifiedLambda; + + +let explicitCFunction: (this: C, m: number) => number; +let explicitPropertyFunction: (this: {n: number}, m: number) => number; +c.explicitC = explicitCFunction; +c.explicitC = function(this: C, m: number) { return this.n + m }; +c.explicitProperty = explicitPropertyFunction; +c.explicitProperty = function(this: {n: number}, m: number) { return this.n + m }; +c.explicitProperty = reconstructed.explicitProperty; + +// lambdas are assignable to anything +c.explicitC = m => m; +c.explicitThis = m => m; +c.explicitProperty = m => m; + +// this inside lambdas refer to outer scope +// the outer-scoped lambda at top-level is still just `any` +c.explicitC = m => m + this.n; +c.explicitThis = m => m + this.n; +c.explicitProperty = m => m + this.n; + +//NOTE: this=C here, I guess? +c.explicitThis = explicitCFunction; +c.explicitThis = function(this: C, m: number) { return this.n + m }; + +// this:any compatibility +c.explicitC = function(m: number) { return this.n + m }; +c.explicitProperty = function(m: number) { return this.n + m }; +c.explicitThis = function(m: number) { return this.n + m }; +c.implicitThis = function(m: number) { return this.n + m }; +c.implicitThis = reconstructed.implicitThis; + +c.explicitC = function(this: B, m: number) { return this.n + m }; + +// this:void compatibility +c.explicitVoid = n => n; + +// class-based assignability +class Base1 { + x: number; + public implicit(): number { return this.x; } + explicit(this: Base1): number { return this.x; } + static implicitStatic(): number { return this.y; } + static explicitStatic(this: typeof Base1): number { return this.y; } + static y: number; + +} +class Derived1 extends Base1 { + y: number +} +class Base2 { + y: number + implicit(): number { return this.y; } + explicit(this: Base1): number { return this.x; } +} +class Derived2 extends Base2 { + x: number +} +let b1 = new Base1(); +let b2 = new Base2(); +let d1 = new Derived1(); +let d2 = new Derived2(); +d2.implicit = d1.implicit // ok, 'x' and 'y' in { x, y } (d assignable to f and vice versa) +d1.implicit = d2.implicit // ok, 'x' and 'y' in { x, y } (f assignable to d and vice versa) + +// bivariance-allowed cases +d1.implicit = b2.implicit // ok, 'y' in D: { x, y } (d assignable e) +d2.implicit = d1.explicit // ok, 'y' in { x, y } (c assignable to f) +b1.implicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) +b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) + +////// use this-type for construction with new //// +function InterfaceThis(this: I) { + this.a = 12; +} +function LiteralTypeThis(this: {x: string}) { + this.x = "ok"; +} +function AnyThis(this: any) { + this.x = "ok"; +} +let interfaceThis = new InterfaceThis(); +let literalTypeThis = new LiteralTypeThis(); +let anyThis = new AnyThis(); + +//// type parameter inference //// +declare var f: { + (this: void, x: number): number, + call(this: (...argArray: any[]) => U, ...argArray: any[]): U; +}; +let n: number = f.call(12); + +function missingTypeIsImplicitAny(this, a: number) { return a; } + +//// [thisTypeInFunctions.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; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var _this = this; +// body checking +var C = (function () { + function C() { + } + C.prototype.explicitThis = function (m) { + return this.n + m; + }; + C.prototype.implicitThis = function (m) { + return this.n + m; + }; + C.prototype.explicitC = function (m) { + return this.n + m; + }; + C.prototype.explicitProperty = function (m) { + return this.n + m; + }; + C.prototype.explicitVoid = function (m) { + return m + 1; + }; + return C; +}()); +var D = (function (_super) { + __extends(D, _super); + function D() { + _super.apply(this, arguments); + } + return D; +}(C)); +var B = (function () { + function B() { + } + return B; +}()); +function explicitStructural(x) { + return x + this.y; +} +function justThis() { + return this.y; +} +function implicitThis(n) { + return 12; +} +var impl = { + a: 12, + explicitVoid2: function () { return _this.a; }, + explicitVoid1: function () { return 12; }, + explicitStructural: function () { + return this.a; + }, + explicitInterface: function () { + return this.a; + }, + explicitThis: function () { + return this.a; + }, + implicitMethod: function () { + return this.a; + }, + implicitFunction: function () { return _this.a; } +}; +impl.explicitVoid1 = function () { return 12; }; +impl.explicitVoid2 = function () { return 12; }; +impl.explicitStructural = function () { return this.a; }; +impl.explicitInterface = function () { return this.a; }; +impl.explicitStructural = function () { return 12; }; +impl.explicitInterface = function () { return 12; }; +impl.explicitThis = function () { return this.a; }; +impl.implicitMethod = function () { return this.a; }; +impl.implicitMethod = function () { return 12; }; +impl.implicitFunction = function () { return _this.a; }; // ok, this: any because it refers to some outer object (window?) +// parameter checking +var ok = { y: 12, f: explicitStructural }; +var implicitAnyOk = { notSpecified: 12, f: implicitThis }; +ok.f(13); +implicitThis(12); +implicitAnyOk.f(12); +var c = new C(); +var d = new D(); +var ripped = c.explicitC; +c.explicitC(12); +c.explicitProperty(12); +c.explicitThis(12); +c.implicitThis(12); +d.explicitC(12); +d.explicitProperty(12); +d.explicitThis(12); +d.implicitThis(12); +var reconstructed = { + n: 12, + explicitThis: c.explicitThis, + implicitThis: c.implicitThis, + explicitC: c.explicitC, + explicitProperty: c.explicitProperty, + explicitVoid: c.explicitVoid +}; +reconstructed.explicitProperty(11); +reconstructed.implicitThis(11); +// assignment checking +var unboundToSpecified = function (x) { return x + _this.y; }; // ok, this:any +var specifiedToSpecified = explicitStructural; +var anyToSpecified = function (x) { return x + 12; }; +var unspecifiedLambda = function (x) { return x + 12; }; +var specifiedLambda = function (x) { return x + 12; }; +var unspecifiedLambdaToSpecified = unspecifiedLambda; +var specifiedLambdaToSpecified = specifiedLambda; +var explicitCFunction; +var explicitPropertyFunction; +c.explicitC = explicitCFunction; +c.explicitC = function (m) { return this.n + m; }; +c.explicitProperty = explicitPropertyFunction; +c.explicitProperty = function (m) { return this.n + m; }; +c.explicitProperty = reconstructed.explicitProperty; +// lambdas are assignable to anything +c.explicitC = function (m) { return m; }; +c.explicitThis = function (m) { return m; }; +c.explicitProperty = function (m) { return m; }; +// this inside lambdas refer to outer scope +// the outer-scoped lambda at top-level is still just `any` +c.explicitC = function (m) { return m + _this.n; }; +c.explicitThis = function (m) { return m + _this.n; }; +c.explicitProperty = function (m) { return m + _this.n; }; +//NOTE: this=C here, I guess? +c.explicitThis = explicitCFunction; +c.explicitThis = function (m) { return this.n + m; }; +// this:any compatibility +c.explicitC = function (m) { return this.n + m; }; +c.explicitProperty = function (m) { return this.n + m; }; +c.explicitThis = function (m) { return this.n + m; }; +c.implicitThis = function (m) { return this.n + m; }; +c.implicitThis = reconstructed.implicitThis; +c.explicitC = function (m) { return this.n + m; }; +// this:void compatibility +c.explicitVoid = function (n) { return n; }; +// class-based assignability +var Base1 = (function () { + function Base1() { + } + Base1.prototype.implicit = function () { return this.x; }; + Base1.prototype.explicit = function () { return this.x; }; + Base1.implicitStatic = function () { return this.y; }; + Base1.explicitStatic = function () { return this.y; }; + return Base1; +}()); +var Derived1 = (function (_super) { + __extends(Derived1, _super); + function Derived1() { + _super.apply(this, arguments); + } + return Derived1; +}(Base1)); +var Base2 = (function () { + function Base2() { + } + Base2.prototype.implicit = function () { return this.y; }; + Base2.prototype.explicit = function () { return this.x; }; + return Base2; +}()); +var Derived2 = (function (_super) { + __extends(Derived2, _super); + function Derived2() { + _super.apply(this, arguments); + } + return Derived2; +}(Base2)); +var b1 = new Base1(); +var b2 = new Base2(); +var d1 = new Derived1(); +var d2 = new Derived2(); +d2.implicit = d1.implicit; // ok, 'x' and 'y' in { x, y } (d assignable to f and vice versa) +d1.implicit = d2.implicit; // ok, 'x' and 'y' in { x, y } (f assignable to d and vice versa) +// bivariance-allowed cases +d1.implicit = b2.implicit; // ok, 'y' in D: { x, y } (d assignable e) +d2.implicit = d1.explicit; // ok, 'y' in { x, y } (c assignable to f) +b1.implicit = d2.implicit; // ok, 'x' and 'y' not in C: { x } (c assignable to f) +b1.explicit = d2.implicit; // ok, 'x' and 'y' not in C: { x } (c assignable to f) +////// use this-type for construction with new //// +function InterfaceThis() { + this.a = 12; +} +function LiteralTypeThis() { + this.x = "ok"; +} +function AnyThis() { + this.x = "ok"; +} +var interfaceThis = new InterfaceThis(); +var literalTypeThis = new LiteralTypeThis(); +var anyThis = new AnyThis(); +var n = f.call(12); +function missingTypeIsImplicitAny(a) { return a; } diff --git a/tests/baselines/reference/thisTypeInFunctions.symbols b/tests/baselines/reference/thisTypeInFunctions.symbols new file mode 100644 index 00000000000..1d9ebbd0cf4 --- /dev/null +++ b/tests/baselines/reference/thisTypeInFunctions.symbols @@ -0,0 +1,862 @@ +=== tests/cases/conformance/types/thisType/thisTypeInFunctions.ts === +// body checking +class C { +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) + + n: number; +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) + + explicitThis(this: this, m: number): number { +>explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 3, 17)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 3, 28)) + + return this.n + m; +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 3, 28)) + } + implicitThis(m: number): number { +>implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 6, 17)) + + return this.n + m; +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 6, 17)) + } + explicitC(this: C, m: number): number { +>explicitC : Symbol(explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 9, 14)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 9, 22)) + + return this.n + m; +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 9, 22)) + } + explicitProperty(this: {n: number}, m: number): number { +>explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 12, 21)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 12, 39)) + + return this.n + m; +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 12, 26)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 12, 39)) + } + explicitVoid(this: void, m: number): number { +>explicitVoid : Symbol(explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 15, 17)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 15, 28)) + + return m + 1; +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 15, 28)) + } +} +class D extends C { } +>D : Symbol(D, Decl(thisTypeInFunctions.ts, 18, 1)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) + +class B { +>B : Symbol(B, Decl(thisTypeInFunctions.ts, 19, 21)) + + n: number; +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 20, 9)) +} +interface I { +>I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) + + a: number; +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 23, 13)) + + explicitVoid1(this: void): number; +>explicitVoid1 : Symbol(explicitVoid1, Decl(thisTypeInFunctions.ts, 24, 14)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 25, 18)) + + explicitVoid2(this: void): number; +>explicitVoid2 : Symbol(explicitVoid2, Decl(thisTypeInFunctions.ts, 25, 38)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 26, 18)) + + explicitStructural(this: {a: number}): number; +>explicitStructural : Symbol(explicitStructural, Decl(thisTypeInFunctions.ts, 26, 38)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 27, 23)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 27, 30)) + + explicitInterface(this: I): number; +>explicitInterface : Symbol(explicitInterface, Decl(thisTypeInFunctions.ts, 27, 50)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 28, 22)) +>I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) + + explicitThis(this: this): number; +>explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 28, 39)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 29, 17)) + + implicitMethod(): number; +>implicitMethod : Symbol(implicitMethod, Decl(thisTypeInFunctions.ts, 29, 37)) + + implicitFunction: () => number; +>implicitFunction : Symbol(implicitFunction, Decl(thisTypeInFunctions.ts, 30, 29)) +} +function explicitStructural(this: { y: number }, x: number): number { +>explicitStructural : Symbol(explicitStructural, Decl(thisTypeInFunctions.ts, 32, 1)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 33, 28)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 33, 35)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 33, 48)) + + return x + this.y; +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 33, 48)) +>this.y : Symbol(y, Decl(thisTypeInFunctions.ts, 33, 35)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 33, 33)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 33, 35)) +} +function justThis(this: { y: number }): number { +>justThis : Symbol(justThis, Decl(thisTypeInFunctions.ts, 35, 1)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 36, 18)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 36, 25)) + + return this.y; +>this.y : Symbol(y, Decl(thisTypeInFunctions.ts, 36, 25)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 36, 23)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 36, 25)) +} +function implicitThis(n: number): number { +>implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 38, 1)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 39, 22)) + + return 12; +} +let impl: I = { +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) + + a: 12, +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 42, 15)) + + explicitVoid2: () => this.a, // ok, this: any because it refers to some outer object (window?) +>explicitVoid2 : Symbol(explicitVoid2, Decl(thisTypeInFunctions.ts, 43, 10)) + + explicitVoid1() { return 12; }, +>explicitVoid1 : Symbol(explicitVoid1, Decl(thisTypeInFunctions.ts, 44, 32)) + + explicitStructural() { +>explicitStructural : Symbol(explicitStructural, Decl(thisTypeInFunctions.ts, 45, 35)) + + return this.a; +>this.a : Symbol(a, Decl(thisTypeInFunctions.ts, 27, 30)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 27, 28)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 27, 30)) + + }, + explicitInterface() { +>explicitInterface : Symbol(explicitInterface, Decl(thisTypeInFunctions.ts, 48, 6)) + + return this.a; +>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) + + }, + explicitThis() { +>explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 51, 6)) + + return this.a; +>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) + + }, + implicitMethod() { +>implicitMethod : Symbol(implicitMethod, Decl(thisTypeInFunctions.ts, 54, 6)) + + return this.a; +>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) + + }, + implicitFunction: () => this.a, // ok, this: any because it refers to some outer object (window?) +>implicitFunction : Symbol(implicitFunction, Decl(thisTypeInFunctions.ts, 57, 6)) +} +impl.explicitVoid1 = function () { return 12; }; +>impl.explicitVoid1 : Symbol(I.explicitVoid1, Decl(thisTypeInFunctions.ts, 24, 14)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>explicitVoid1 : Symbol(I.explicitVoid1, Decl(thisTypeInFunctions.ts, 24, 14)) + +impl.explicitVoid2 = () => 12; +>impl.explicitVoid2 : Symbol(I.explicitVoid2, Decl(thisTypeInFunctions.ts, 25, 38)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>explicitVoid2 : Symbol(I.explicitVoid2, Decl(thisTypeInFunctions.ts, 25, 38)) + +impl.explicitStructural = function() { return this.a; }; +>impl.explicitStructural : Symbol(I.explicitStructural, Decl(thisTypeInFunctions.ts, 26, 38)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>explicitStructural : Symbol(I.explicitStructural, Decl(thisTypeInFunctions.ts, 26, 38)) +>this.a : Symbol(a, Decl(thisTypeInFunctions.ts, 27, 30)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 27, 28)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 27, 30)) + +impl.explicitInterface = function() { return this.a; }; +>impl.explicitInterface : Symbol(I.explicitInterface, Decl(thisTypeInFunctions.ts, 27, 50)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>explicitInterface : Symbol(I.explicitInterface, Decl(thisTypeInFunctions.ts, 27, 50)) +>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) + +impl.explicitStructural = () => 12; +>impl.explicitStructural : Symbol(I.explicitStructural, Decl(thisTypeInFunctions.ts, 26, 38)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>explicitStructural : Symbol(I.explicitStructural, Decl(thisTypeInFunctions.ts, 26, 38)) + +impl.explicitInterface = () => 12; +>impl.explicitInterface : Symbol(I.explicitInterface, Decl(thisTypeInFunctions.ts, 27, 50)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>explicitInterface : Symbol(I.explicitInterface, Decl(thisTypeInFunctions.ts, 27, 50)) + +impl.explicitThis = function () { return this.a; }; +>impl.explicitThis : Symbol(I.explicitThis, Decl(thisTypeInFunctions.ts, 28, 39)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>explicitThis : Symbol(I.explicitThis, Decl(thisTypeInFunctions.ts, 28, 39)) +>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) + +impl.implicitMethod = function () { return this.a; }; +>impl.implicitMethod : Symbol(I.implicitMethod, Decl(thisTypeInFunctions.ts, 29, 37)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>implicitMethod : Symbol(I.implicitMethod, Decl(thisTypeInFunctions.ts, 29, 37)) +>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) + +impl.implicitMethod = () => 12; +>impl.implicitMethod : Symbol(I.implicitMethod, Decl(thisTypeInFunctions.ts, 29, 37)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>implicitMethod : Symbol(I.implicitMethod, Decl(thisTypeInFunctions.ts, 29, 37)) + +impl.implicitFunction = () => this.a; // ok, this: any because it refers to some outer object (window?) +>impl.implicitFunction : Symbol(I.implicitFunction, Decl(thisTypeInFunctions.ts, 30, 29)) +>impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) +>implicitFunction : Symbol(I.implicitFunction, Decl(thisTypeInFunctions.ts, 30, 29)) + +// parameter checking +let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, f: explicitStructural }; +>ok : Symbol(ok, Decl(thisTypeInFunctions.ts, 71, 3)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 71, 9)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 71, 19)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 71, 24)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 71, 31)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 71, 44)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 71, 70)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 71, 77)) +>explicitStructural : Symbol(explicitStructural, Decl(thisTypeInFunctions.ts, 32, 1)) + +let implicitAnyOk: {notSpecified: number, f: (x: number) => number} = { notSpecified: 12, f: implicitThis }; +>implicitAnyOk : Symbol(implicitAnyOk, Decl(thisTypeInFunctions.ts, 72, 3)) +>notSpecified : Symbol(notSpecified, Decl(thisTypeInFunctions.ts, 72, 20)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 72, 41)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 72, 46)) +>notSpecified : Symbol(notSpecified, Decl(thisTypeInFunctions.ts, 72, 71)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 72, 89)) +>implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 38, 1)) + +ok.f(13); +>ok.f : Symbol(f, Decl(thisTypeInFunctions.ts, 71, 19)) +>ok : Symbol(ok, Decl(thisTypeInFunctions.ts, 71, 3)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 71, 19)) + +implicitThis(12); +>implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 38, 1)) + +implicitAnyOk.f(12); +>implicitAnyOk.f : Symbol(f, Decl(thisTypeInFunctions.ts, 72, 41)) +>implicitAnyOk : Symbol(implicitAnyOk, Decl(thisTypeInFunctions.ts, 72, 3)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 72, 41)) + +let c = new C(); +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) + +let d = new D(); +>d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) +>D : Symbol(D, Decl(thisTypeInFunctions.ts, 18, 1)) + +let ripped = c.explicitC; +>ripped : Symbol(ripped, Decl(thisTypeInFunctions.ts, 79, 3)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) + +c.explicitC(12); +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) + +c.explicitProperty(12); +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) + +c.explicitThis(12); +>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) + +c.implicitThis(12); +>c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) + +d.explicitC(12); +>d.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) + +d.explicitProperty(12); +>d.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) + +d.explicitThis(12); +>d.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) + +d.implicitThis(12); +>d.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) +>implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) + +let reconstructed: { +>reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 88, 3)) + + n: number, +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 88, 20)) + + explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. +>explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 89, 14)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 90, 17)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 90, 25)) + + implicitThis(m: number): number, +>implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 90, 45)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 91, 17)) + + explicitC(this: C, m: number): number, +>explicitC : Symbol(explicitC, Decl(thisTypeInFunctions.ts, 91, 36)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 92, 14)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 92, 22)) + + explicitProperty: (this: {n : number}, m: number) => number, +>explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 92, 42)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 93, 23)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 93, 30)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 93, 42)) + + explicitVoid(this: void, m: number): number, +>explicitVoid : Symbol(explicitVoid, Decl(thisTypeInFunctions.ts, 93, 64)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 94, 17)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 94, 28)) + +} = { + n: 12, +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 95, 5)) + + explicitThis: c.explicitThis, +>explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 96, 10)) +>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) + + implicitThis: c.implicitThis, +>implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 97, 33)) +>c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) + + explicitC: c.explicitC, +>explicitC : Symbol(explicitC, Decl(thisTypeInFunctions.ts, 98, 33)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) + + explicitProperty: c.explicitProperty, +>explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 99, 27)) +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) + + explicitVoid: c.explicitVoid +>explicitVoid : Symbol(explicitVoid, Decl(thisTypeInFunctions.ts, 100, 41)) +>c.explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) + +}; +reconstructed.explicitProperty(11); +>reconstructed.explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 92, 42)) +>reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 88, 3)) +>explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 92, 42)) + +reconstructed.implicitThis(11); +>reconstructed.implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 90, 45)) +>reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 88, 3)) +>implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 90, 45)) + +// assignment checking +let unboundToSpecified: (this: { y: number }, x: number) => number = x => x + this.y; // ok, this:any +>unboundToSpecified : Symbol(unboundToSpecified, Decl(thisTypeInFunctions.ts, 107, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 107, 25)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 107, 32)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 107, 45)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 107, 68)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 107, 68)) + +let specifiedToSpecified: (this: {y: number}, x: number) => number = explicitStructural; +>specifiedToSpecified : Symbol(specifiedToSpecified, Decl(thisTypeInFunctions.ts, 108, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 108, 27)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 108, 34)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 108, 45)) +>explicitStructural : Symbol(explicitStructural, Decl(thisTypeInFunctions.ts, 32, 1)) + +let anyToSpecified: (this: { y: number }, x: number) => number = function(x: number): number { return x + 12; }; +>anyToSpecified : Symbol(anyToSpecified, Decl(thisTypeInFunctions.ts, 109, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 109, 21)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 109, 28)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 109, 41)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 109, 74)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 109, 74)) + +let unspecifiedLambda: (x: number) => number = x => x + 12; +>unspecifiedLambda : Symbol(unspecifiedLambda, Decl(thisTypeInFunctions.ts, 111, 3)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 111, 24)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 111, 46)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 111, 46)) + +let specifiedLambda: (this: void, x: number) => number = x => x + 12; +>specifiedLambda : Symbol(specifiedLambda, Decl(thisTypeInFunctions.ts, 112, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 112, 22)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 112, 33)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 112, 56)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 112, 56)) + +let unspecifiedLambdaToSpecified: (this: {y: number}, x: number) => number = unspecifiedLambda; +>unspecifiedLambdaToSpecified : Symbol(unspecifiedLambdaToSpecified, Decl(thisTypeInFunctions.ts, 113, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 113, 35)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 113, 42)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 113, 53)) +>unspecifiedLambda : Symbol(unspecifiedLambda, Decl(thisTypeInFunctions.ts, 111, 3)) + +let specifiedLambdaToSpecified: (this: {y: number}, x: number) => number = specifiedLambda; +>specifiedLambdaToSpecified : Symbol(specifiedLambdaToSpecified, Decl(thisTypeInFunctions.ts, 114, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 114, 33)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 114, 40)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 114, 51)) +>specifiedLambda : Symbol(specifiedLambda, Decl(thisTypeInFunctions.ts, 112, 3)) + + +let explicitCFunction: (this: C, m: number) => number; +>explicitCFunction : Symbol(explicitCFunction, Decl(thisTypeInFunctions.ts, 117, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 117, 24)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 117, 32)) + +let explicitPropertyFunction: (this: {n: number}, m: number) => number; +>explicitPropertyFunction : Symbol(explicitPropertyFunction, Decl(thisTypeInFunctions.ts, 118, 3)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 118, 31)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 118, 38)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 118, 49)) + +c.explicitC = explicitCFunction; +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>explicitCFunction : Symbol(explicitCFunction, Decl(thisTypeInFunctions.ts, 117, 3)) + +c.explicitC = function(this: C, m: number) { return this.n + m }; +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 120, 23)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 120, 31)) +>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 120, 31)) + +c.explicitProperty = explicitPropertyFunction; +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>explicitPropertyFunction : Symbol(explicitPropertyFunction, Decl(thisTypeInFunctions.ts, 118, 3)) + +c.explicitProperty = function(this: {n: number}, m: number) { return this.n + m }; +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 122, 30)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 122, 37)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 122, 48)) +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 122, 37)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 122, 35)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 122, 37)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 122, 48)) + +c.explicitProperty = reconstructed.explicitProperty; +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>reconstructed.explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 92, 42)) +>reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 88, 3)) +>explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 92, 42)) + +// lambdas are assignable to anything +c.explicitC = m => m; +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 126, 13)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 126, 13)) + +c.explicitThis = m => m; +>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 127, 16)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 127, 16)) + +c.explicitProperty = m => m; +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 128, 20)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 128, 20)) + +// this inside lambdas refer to outer scope +// the outer-scoped lambda at top-level is still just `any` +c.explicitC = m => m + this.n; +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 132, 13)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 132, 13)) + +c.explicitThis = m => m + this.n; +>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 133, 16)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 133, 16)) + +c.explicitProperty = m => m + this.n; +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 134, 20)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 134, 20)) + +//NOTE: this=C here, I guess? +c.explicitThis = explicitCFunction; +>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>explicitCFunction : Symbol(explicitCFunction, Decl(thisTypeInFunctions.ts, 117, 3)) + +c.explicitThis = function(this: C, m: number) { return this.n + m }; +>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 138, 26)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 138, 34)) +>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 138, 34)) + +// this:any compatibility +c.explicitC = function(m: number) { return this.n + m }; +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 141, 23)) +>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 141, 23)) + +c.explicitProperty = function(m: number) { return this.n + m }; +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 142, 30)) +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 12, 26)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 142, 30)) + +c.explicitThis = function(m: number) { return this.n + m }; +>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 143, 26)) +>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 143, 26)) + +c.implicitThis = function(m: number) { return this.n + m }; +>c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 144, 26)) +>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 144, 26)) + +c.implicitThis = reconstructed.implicitThis; +>c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>reconstructed.implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 90, 45)) +>reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 88, 3)) +>implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 90, 45)) + +c.explicitC = function(this: B, m: number) { return this.n + m }; +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 147, 23)) +>B : Symbol(B, Decl(thisTypeInFunctions.ts, 19, 21)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 147, 31)) +>this.n : Symbol(B.n, Decl(thisTypeInFunctions.ts, 20, 9)) +>this : Symbol(B, Decl(thisTypeInFunctions.ts, 19, 21)) +>n : Symbol(B.n, Decl(thisTypeInFunctions.ts, 20, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 147, 31)) + +// this:void compatibility +c.explicitVoid = n => n; +>c.explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) +>c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) +>explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 150, 16)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 150, 16)) + +// class-based assignability +class Base1 { +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) + + x: number; +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 153, 13)) + + public implicit(): number { return this.x; } +>implicit : Symbol(implicit, Decl(thisTypeInFunctions.ts, 154, 14)) +>this.x : Symbol(x, Decl(thisTypeInFunctions.ts, 153, 13)) +>this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 153, 13)) + + explicit(this: Base1): number { return this.x; } +>explicit : Symbol(explicit, Decl(thisTypeInFunctions.ts, 155, 48)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 156, 13)) +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) +>this.x : Symbol(x, Decl(thisTypeInFunctions.ts, 153, 13)) +>this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 153, 13)) + + static implicitStatic(): number { return this.y; } +>implicitStatic : Symbol(Base1.implicitStatic, Decl(thisTypeInFunctions.ts, 156, 52)) +>this.y : Symbol(Base1.y, Decl(thisTypeInFunctions.ts, 158, 72)) +>this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) +>y : Symbol(Base1.y, Decl(thisTypeInFunctions.ts, 158, 72)) + + static explicitStatic(this: typeof Base1): number { return this.y; } +>explicitStatic : Symbol(Base1.explicitStatic, Decl(thisTypeInFunctions.ts, 157, 54)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 158, 26)) +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) +>this.y : Symbol(Base1.y, Decl(thisTypeInFunctions.ts, 158, 72)) +>this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) +>y : Symbol(Base1.y, Decl(thisTypeInFunctions.ts, 158, 72)) + + static y: number; +>y : Symbol(Base1.y, Decl(thisTypeInFunctions.ts, 158, 72)) + +} +class Derived1 extends Base1 { +>Derived1 : Symbol(Derived1, Decl(thisTypeInFunctions.ts, 161, 1)) +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) + + y: number +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 162, 30)) +} +class Base2 { +>Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 164, 1)) + + y: number +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 165, 13)) + + implicit(): number { return this.y; } +>implicit : Symbol(implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +>this.y : Symbol(y, Decl(thisTypeInFunctions.ts, 165, 13)) +>this : Symbol(Base2, Decl(thisTypeInFunctions.ts, 164, 1)) +>y : Symbol(y, Decl(thisTypeInFunctions.ts, 165, 13)) + + explicit(this: Base1): number { return this.x; } +>explicit : Symbol(explicit, Decl(thisTypeInFunctions.ts, 167, 41)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 168, 13)) +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) +>this.x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 153, 13)) +>this : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) +>x : Symbol(Base1.x, Decl(thisTypeInFunctions.ts, 153, 13)) +} +class Derived2 extends Base2 { +>Derived2 : Symbol(Derived2, Decl(thisTypeInFunctions.ts, 169, 1)) +>Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 164, 1)) + + x: number +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 170, 30)) +} +let b1 = new Base1(); +>b1 : Symbol(b1, Decl(thisTypeInFunctions.ts, 173, 3)) +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) + +let b2 = new Base2(); +>b2 : Symbol(b2, Decl(thisTypeInFunctions.ts, 174, 3)) +>Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 164, 1)) + +let d1 = new Derived1(); +>d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 175, 3)) +>Derived1 : Symbol(Derived1, Decl(thisTypeInFunctions.ts, 161, 1)) + +let d2 = new Derived2(); +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 176, 3)) +>Derived2 : Symbol(Derived2, Decl(thisTypeInFunctions.ts, 169, 1)) + +d2.implicit = d1.implicit // ok, 'x' and 'y' in { x, y } (d assignable to f and vice versa) +>d2.implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 176, 3)) +>implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +>d1.implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) +>d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 175, 3)) +>implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) + +d1.implicit = d2.implicit // ok, 'x' and 'y' in { x, y } (f assignable to d and vice versa) +>d1.implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) +>d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 175, 3)) +>implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) +>d2.implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 176, 3)) +>implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) + +// bivariance-allowed cases +d1.implicit = b2.implicit // ok, 'y' in D: { x, y } (d assignable e) +>d1.implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) +>d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 175, 3)) +>implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) +>b2.implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +>b2 : Symbol(b2, Decl(thisTypeInFunctions.ts, 174, 3)) +>implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) + +d2.implicit = d1.explicit // ok, 'y' in { x, y } (c assignable to f) +>d2.implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 176, 3)) +>implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +>d1.explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 155, 48)) +>d1 : Symbol(d1, Decl(thisTypeInFunctions.ts, 175, 3)) +>explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 155, 48)) + +b1.implicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) +>b1.implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) +>b1 : Symbol(b1, Decl(thisTypeInFunctions.ts, 173, 3)) +>implicit : Symbol(Base1.implicit, Decl(thisTypeInFunctions.ts, 154, 14)) +>d2.implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 176, 3)) +>implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) + +b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) +>b1.explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 155, 48)) +>b1 : Symbol(b1, Decl(thisTypeInFunctions.ts, 173, 3)) +>explicit : Symbol(Base1.explicit, Decl(thisTypeInFunctions.ts, 155, 48)) +>d2.implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +>d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 176, 3)) +>implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) + +////// use this-type for construction with new //// +function InterfaceThis(this: I) { +>InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 184, 25)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 187, 23)) +>I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) + + this.a = 12; +>this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) +} +function LiteralTypeThis(this: {x: string}) { +>LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 189, 1)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 190, 25)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 190, 32)) + + this.x = "ok"; +>this.x : Symbol(x, Decl(thisTypeInFunctions.ts, 190, 32)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 190, 30)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 190, 32)) +} +function AnyThis(this: any) { +>AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 192, 1)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 193, 17)) + + this.x = "ok"; +} +let interfaceThis = new InterfaceThis(); +>interfaceThis : Symbol(interfaceThis, Decl(thisTypeInFunctions.ts, 196, 3)) +>InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 184, 25)) + +let literalTypeThis = new LiteralTypeThis(); +>literalTypeThis : Symbol(literalTypeThis, Decl(thisTypeInFunctions.ts, 197, 3)) +>LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 189, 1)) + +let anyThis = new AnyThis(); +>anyThis : Symbol(anyThis, Decl(thisTypeInFunctions.ts, 198, 3)) +>AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 192, 1)) + +//// type parameter inference //// +declare var f: { +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 201, 11)) + + (this: void, x: number): number, +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 202, 5)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 202, 16)) + + call(this: (...argArray: any[]) => U, ...argArray: any[]): U; +>call : Symbol(call, Decl(thisTypeInFunctions.ts, 202, 36)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 203, 9)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 203, 12)) +>argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 203, 19)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 203, 9)) +>argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 203, 44)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 203, 9)) + +}; +let n: number = f.call(12); +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 205, 3)) +>f.call : Symbol(call, Decl(thisTypeInFunctions.ts, 202, 36)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 201, 11)) +>call : Symbol(call, Decl(thisTypeInFunctions.ts, 202, 36)) + +function missingTypeIsImplicitAny(this, a: number) { return a; } +>missingTypeIsImplicitAny : Symbol(missingTypeIsImplicitAny, Decl(thisTypeInFunctions.ts, 205, 27)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 207, 34)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 207, 39)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 207, 39)) + diff --git a/tests/baselines/reference/thisTypeInFunctions.types b/tests/baselines/reference/thisTypeInFunctions.types new file mode 100644 index 00000000000..36b458b91e0 --- /dev/null +++ b/tests/baselines/reference/thisTypeInFunctions.types @@ -0,0 +1,1037 @@ +=== tests/cases/conformance/types/thisType/thisTypeInFunctions.ts === +// body checking +class C { +>C : C + + n: number; +>n : number + + explicitThis(this: this, m: number): number { +>explicitThis : (this: this, m: number) => number +>this : this +>m : number + + return this.n + m; +>this.n + m : number +>this.n : number +>this : this +>n : number +>m : number + } + implicitThis(m: number): number { +>implicitThis : (this: this, m: number) => number +>m : number + + return this.n + m; +>this.n + m : number +>this.n : number +>this : this +>n : number +>m : number + } + explicitC(this: C, m: number): number { +>explicitC : (this: C, m: number) => number +>this : C +>C : C +>m : number + + return this.n + m; +>this.n + m : number +>this.n : number +>this : C +>n : number +>m : number + } + explicitProperty(this: {n: number}, m: number): number { +>explicitProperty : (this: { n: number; }, m: number) => number +>this : { n: number; } +>n : number +>m : number + + return this.n + m; +>this.n + m : number +>this.n : number +>this : { n: number; } +>n : number +>m : number + } + explicitVoid(this: void, m: number): number { +>explicitVoid : (m: number) => number +>this : void +>m : number + + return m + 1; +>m + 1 : number +>m : number +>1 : number + } +} +class D extends C { } +>D : D +>C : C + +class B { +>B : B + + n: number; +>n : number +} +interface I { +>I : I + + a: number; +>a : number + + explicitVoid1(this: void): number; +>explicitVoid1 : () => number +>this : void + + explicitVoid2(this: void): number; +>explicitVoid2 : () => number +>this : void + + explicitStructural(this: {a: number}): number; +>explicitStructural : (this: { a: number; }) => number +>this : { a: number; } +>a : number + + explicitInterface(this: I): number; +>explicitInterface : (this: I) => number +>this : I +>I : I + + explicitThis(this: this): number; +>explicitThis : (this: this) => number +>this : this + + implicitMethod(): number; +>implicitMethod : (this: this) => number + + implicitFunction: () => number; +>implicitFunction : () => number +} +function explicitStructural(this: { y: number }, x: number): number { +>explicitStructural : (this: { y: number; }, x: number) => number +>this : { y: number; } +>y : number +>x : number + + return x + this.y; +>x + this.y : number +>x : number +>this.y : number +>this : { y: number; } +>y : number +} +function justThis(this: { y: number }): number { +>justThis : (this: { y: number; }) => number +>this : { y: number; } +>y : number + + return this.y; +>this.y : number +>this : { y: number; } +>y : number +} +function implicitThis(n: number): number { +>implicitThis : (n: number) => number +>n : number + + return 12; +>12 : number +} +let impl: I = { +>impl : I +>I : I +>{ a: 12, explicitVoid2: () => this.a, // ok, this: any because it refers to some outer object (window?) explicitVoid1() { return 12; }, explicitStructural() { return this.a; }, explicitInterface() { return this.a; }, explicitThis() { return this.a; }, implicitMethod() { return this.a; }, implicitFunction: () => this.a, // ok, this: any because it refers to some outer object (window?)} : { a: number; explicitVoid2: () => any; explicitVoid1(): number; explicitStructural(this: { a: number; }): number; explicitInterface(this: I): number; explicitThis(this: I): number; implicitMethod(this: I): number; implicitFunction: () => any; } + + a: 12, +>a : number +>12 : number + + explicitVoid2: () => this.a, // ok, this: any because it refers to some outer object (window?) +>explicitVoid2 : () => any +>() => this.a : () => any +>this.a : any +>this : any +>a : any + + explicitVoid1() { return 12; }, +>explicitVoid1 : () => number +>12 : number + + explicitStructural() { +>explicitStructural : (this: { a: number; }) => number + + return this.a; +>this.a : number +>this : { a: number; } +>a : number + + }, + explicitInterface() { +>explicitInterface : (this: I) => number + + return this.a; +>this.a : number +>this : I +>a : number + + }, + explicitThis() { +>explicitThis : (this: I) => number + + return this.a; +>this.a : number +>this : I +>a : number + + }, + implicitMethod() { +>implicitMethod : (this: I) => number + + return this.a; +>this.a : number +>this : I +>a : number + + }, + implicitFunction: () => this.a, // ok, this: any because it refers to some outer object (window?) +>implicitFunction : () => any +>() => this.a : () => any +>this.a : any +>this : any +>a : any +} +impl.explicitVoid1 = function () { return 12; }; +>impl.explicitVoid1 = function () { return 12; } : () => number +>impl.explicitVoid1 : () => number +>impl : I +>explicitVoid1 : () => number +>function () { return 12; } : () => number +>12 : number + +impl.explicitVoid2 = () => 12; +>impl.explicitVoid2 = () => 12 : () => number +>impl.explicitVoid2 : () => number +>impl : I +>explicitVoid2 : () => number +>() => 12 : () => number +>12 : number + +impl.explicitStructural = function() { return this.a; }; +>impl.explicitStructural = function() { return this.a; } : (this: { a: number; }) => number +>impl.explicitStructural : (this: { a: number; }) => number +>impl : I +>explicitStructural : (this: { a: number; }) => number +>function() { return this.a; } : (this: { a: number; }) => number +>this.a : number +>this : { a: number; } +>a : number + +impl.explicitInterface = function() { return this.a; }; +>impl.explicitInterface = function() { return this.a; } : (this: I) => number +>impl.explicitInterface : (this: I) => number +>impl : I +>explicitInterface : (this: I) => number +>function() { return this.a; } : (this: I) => number +>this.a : number +>this : I +>a : number + +impl.explicitStructural = () => 12; +>impl.explicitStructural = () => 12 : () => number +>impl.explicitStructural : (this: { a: number; }) => number +>impl : I +>explicitStructural : (this: { a: number; }) => number +>() => 12 : () => number +>12 : number + +impl.explicitInterface = () => 12; +>impl.explicitInterface = () => 12 : () => number +>impl.explicitInterface : (this: I) => number +>impl : I +>explicitInterface : (this: I) => number +>() => 12 : () => number +>12 : number + +impl.explicitThis = function () { return this.a; }; +>impl.explicitThis = function () { return this.a; } : (this: I) => number +>impl.explicitThis : (this: I) => number +>impl : I +>explicitThis : (this: I) => number +>function () { return this.a; } : (this: I) => number +>this.a : number +>this : I +>a : number + +impl.implicitMethod = function () { return this.a; }; +>impl.implicitMethod = function () { return this.a; } : (this: I) => number +>impl.implicitMethod : (this: I) => number +>impl : I +>implicitMethod : (this: I) => number +>function () { return this.a; } : (this: I) => number +>this.a : number +>this : I +>a : number + +impl.implicitMethod = () => 12; +>impl.implicitMethod = () => 12 : () => number +>impl.implicitMethod : (this: I) => number +>impl : I +>implicitMethod : (this: I) => number +>() => 12 : () => number +>12 : number + +impl.implicitFunction = () => this.a; // ok, this: any because it refers to some outer object (window?) +>impl.implicitFunction = () => this.a : () => any +>impl.implicitFunction : () => number +>impl : I +>implicitFunction : () => number +>() => this.a : () => any +>this.a : any +>this : any +>a : any + +// parameter checking +let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, f: explicitStructural }; +>ok : { y: number; f: (this: { y: number; }, x: number) => number; } +>y : number +>f : (this: { y: number; }, x: number) => number +>this : { y: number; } +>y : number +>x : number +>{ y: 12, f: explicitStructural } : { y: number; f: (this: { y: number; }, x: number) => number; } +>y : number +>12 : number +>f : (this: { y: number; }, x: number) => number +>explicitStructural : (this: { y: number; }, x: number) => number + +let implicitAnyOk: {notSpecified: number, f: (x: number) => number} = { notSpecified: 12, f: implicitThis }; +>implicitAnyOk : { notSpecified: number; f: (x: number) => number; } +>notSpecified : number +>f : (x: number) => number +>x : number +>{ notSpecified: 12, f: implicitThis } : { notSpecified: number; f: (n: number) => number; } +>notSpecified : number +>12 : number +>f : (n: number) => number +>implicitThis : (n: number) => number + +ok.f(13); +>ok.f(13) : number +>ok.f : (this: { y: number; }, x: number) => number +>ok : { y: number; f: (this: { y: number; }, x: number) => number; } +>f : (this: { y: number; }, x: number) => number +>13 : number + +implicitThis(12); +>implicitThis(12) : number +>implicitThis : (n: number) => number +>12 : number + +implicitAnyOk.f(12); +>implicitAnyOk.f(12) : number +>implicitAnyOk.f : (x: number) => number +>implicitAnyOk : { notSpecified: number; f: (x: number) => number; } +>f : (x: number) => number +>12 : number + +let c = new C(); +>c : C +>new C() : C +>C : typeof C + +let d = new D(); +>d : D +>new D() : D +>D : typeof D + +let ripped = c.explicitC; +>ripped : (this: C, m: number) => number +>c.explicitC : (this: C, m: number) => number +>c : C +>explicitC : (this: C, m: number) => number + +c.explicitC(12); +>c.explicitC(12) : number +>c.explicitC : (this: C, m: number) => number +>c : C +>explicitC : (this: C, m: number) => number +>12 : number + +c.explicitProperty(12); +>c.explicitProperty(12) : number +>c.explicitProperty : (this: { n: number; }, m: number) => number +>c : C +>explicitProperty : (this: { n: number; }, m: number) => number +>12 : number + +c.explicitThis(12); +>c.explicitThis(12) : number +>c.explicitThis : (this: C, m: number) => number +>c : C +>explicitThis : (this: C, m: number) => number +>12 : number + +c.implicitThis(12); +>c.implicitThis(12) : number +>c.implicitThis : (this: C, m: number) => number +>c : C +>implicitThis : (this: C, m: number) => number +>12 : number + +d.explicitC(12); +>d.explicitC(12) : number +>d.explicitC : (this: C, m: number) => number +>d : D +>explicitC : (this: C, m: number) => number +>12 : number + +d.explicitProperty(12); +>d.explicitProperty(12) : number +>d.explicitProperty : (this: { n: number; }, m: number) => number +>d : D +>explicitProperty : (this: { n: number; }, m: number) => number +>12 : number + +d.explicitThis(12); +>d.explicitThis(12) : number +>d.explicitThis : (this: D, m: number) => number +>d : D +>explicitThis : (this: D, m: number) => number +>12 : number + +d.implicitThis(12); +>d.implicitThis(12) : number +>d.implicitThis : (this: D, m: number) => number +>d : D +>implicitThis : (this: D, m: number) => number +>12 : number + +let reconstructed: { +>reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(m: number): number; } + + n: number, +>n : number + + explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. +>explicitThis : (this: C, m: number) => number +>this : C +>C : C +>m : number + + implicitThis(m: number): number, +>implicitThis : (m: number) => number +>m : number + + explicitC(this: C, m: number): number, +>explicitC : (this: C, m: number) => number +>this : C +>C : C +>m : number + + explicitProperty: (this: {n : number}, m: number) => number, +>explicitProperty : (this: { n: number; }, m: number) => number +>this : { n: number; } +>n : number +>m : number + + explicitVoid(this: void, m: number): number, +>explicitVoid : (m: number) => number +>this : void +>m : number + +} = { +>{ n: 12, explicitThis: c.explicitThis, implicitThis: c.implicitThis, explicitC: c.explicitC, explicitProperty: c.explicitProperty, explicitVoid: c.explicitVoid} : { n: number; explicitThis: (this: C, m: number) => number; implicitThis: (this: C, m: number) => number; explicitC: (this: C, m: number) => number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid: (m: number) => number; } + + n: 12, +>n : number +>12 : number + + explicitThis: c.explicitThis, +>explicitThis : (this: C, m: number) => number +>c.explicitThis : (this: C, m: number) => number +>c : C +>explicitThis : (this: C, m: number) => number + + implicitThis: c.implicitThis, +>implicitThis : (this: C, m: number) => number +>c.implicitThis : (this: C, m: number) => number +>c : C +>implicitThis : (this: C, m: number) => number + + explicitC: c.explicitC, +>explicitC : (this: C, m: number) => number +>c.explicitC : (this: C, m: number) => number +>c : C +>explicitC : (this: C, m: number) => number + + explicitProperty: c.explicitProperty, +>explicitProperty : (this: { n: number; }, m: number) => number +>c.explicitProperty : (this: { n: number; }, m: number) => number +>c : C +>explicitProperty : (this: { n: number; }, m: number) => number + + explicitVoid: c.explicitVoid +>explicitVoid : (m: number) => number +>c.explicitVoid : (m: number) => number +>c : C +>explicitVoid : (m: number) => number + +}; +reconstructed.explicitProperty(11); +>reconstructed.explicitProperty(11) : number +>reconstructed.explicitProperty : (this: { n: number; }, m: number) => number +>reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(m: number): number; } +>explicitProperty : (this: { n: number; }, m: number) => number +>11 : number + +reconstructed.implicitThis(11); +>reconstructed.implicitThis(11) : number +>reconstructed.implicitThis : (m: number) => number +>reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(m: number): number; } +>implicitThis : (m: number) => number +>11 : number + +// assignment checking +let unboundToSpecified: (this: { y: number }, x: number) => number = x => x + this.y; // ok, this:any +>unboundToSpecified : (this: { y: number; }, x: number) => number +>this : { y: number; } +>y : number +>x : number +>x => x + this.y : (x: number) => any +>x : number +>x + this.y : any +>x : number +>this.y : any +>this : any +>y : any + +let specifiedToSpecified: (this: {y: number}, x: number) => number = explicitStructural; +>specifiedToSpecified : (this: { y: number; }, x: number) => number +>this : { y: number; } +>y : number +>x : number +>explicitStructural : (this: { y: number; }, x: number) => number + +let anyToSpecified: (this: { y: number }, x: number) => number = function(x: number): number { return x + 12; }; +>anyToSpecified : (this: { y: number; }, x: number) => number +>this : { y: number; } +>y : number +>x : number +>function(x: number): number { return x + 12; } : (this: { y: number; }, x: number) => number +>x : number +>x + 12 : number +>x : number +>12 : number + +let unspecifiedLambda: (x: number) => number = x => x + 12; +>unspecifiedLambda : (x: number) => number +>x : number +>x => x + 12 : (x: number) => number +>x : number +>x + 12 : number +>x : number +>12 : number + +let specifiedLambda: (this: void, x: number) => number = x => x + 12; +>specifiedLambda : (x: number) => number +>this : void +>x : number +>x => x + 12 : (x: number) => number +>x : number +>x + 12 : number +>x : number +>12 : number + +let unspecifiedLambdaToSpecified: (this: {y: number}, x: number) => number = unspecifiedLambda; +>unspecifiedLambdaToSpecified : (this: { y: number; }, x: number) => number +>this : { y: number; } +>y : number +>x : number +>unspecifiedLambda : (x: number) => number + +let specifiedLambdaToSpecified: (this: {y: number}, x: number) => number = specifiedLambda; +>specifiedLambdaToSpecified : (this: { y: number; }, x: number) => number +>this : { y: number; } +>y : number +>x : number +>specifiedLambda : (x: number) => number + + +let explicitCFunction: (this: C, m: number) => number; +>explicitCFunction : (this: C, m: number) => number +>this : C +>C : C +>m : number + +let explicitPropertyFunction: (this: {n: number}, m: number) => number; +>explicitPropertyFunction : (this: { n: number; }, m: number) => number +>this : { n: number; } +>n : number +>m : number + +c.explicitC = explicitCFunction; +>c.explicitC = explicitCFunction : (this: C, m: number) => number +>c.explicitC : (this: C, m: number) => number +>c : C +>explicitC : (this: C, m: number) => number +>explicitCFunction : (this: C, m: number) => number + +c.explicitC = function(this: C, m: number) { return this.n + m }; +>c.explicitC = function(this: C, m: number) { return this.n + m } : (this: C, m: number) => number +>c.explicitC : (this: C, m: number) => number +>c : C +>explicitC : (this: C, m: number) => number +>function(this: C, m: number) { return this.n + m } : (this: C, m: number) => number +>this : C +>C : C +>m : number +>this.n + m : number +>this.n : number +>this : C +>n : number +>m : number + +c.explicitProperty = explicitPropertyFunction; +>c.explicitProperty = explicitPropertyFunction : (this: { n: number; }, m: number) => number +>c.explicitProperty : (this: { n: number; }, m: number) => number +>c : C +>explicitProperty : (this: { n: number; }, m: number) => number +>explicitPropertyFunction : (this: { n: number; }, m: number) => number + +c.explicitProperty = function(this: {n: number}, m: number) { return this.n + m }; +>c.explicitProperty = function(this: {n: number}, m: number) { return this.n + m } : (this: { n: number; }, m: number) => number +>c.explicitProperty : (this: { n: number; }, m: number) => number +>c : C +>explicitProperty : (this: { n: number; }, m: number) => number +>function(this: {n: number}, m: number) { return this.n + m } : (this: { n: number; }, m: number) => number +>this : { n: number; } +>n : number +>m : number +>this.n + m : number +>this.n : number +>this : { n: number; } +>n : number +>m : number + +c.explicitProperty = reconstructed.explicitProperty; +>c.explicitProperty = reconstructed.explicitProperty : (this: { n: number; }, m: number) => number +>c.explicitProperty : (this: { n: number; }, m: number) => number +>c : C +>explicitProperty : (this: { n: number; }, m: number) => number +>reconstructed.explicitProperty : (this: { n: number; }, m: number) => number +>reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(m: number): number; } +>explicitProperty : (this: { n: number; }, m: number) => number + +// lambdas are assignable to anything +c.explicitC = m => m; +>c.explicitC = m => m : (m: number) => number +>c.explicitC : (this: C, m: number) => number +>c : C +>explicitC : (this: C, m: number) => number +>m => m : (m: number) => number +>m : number +>m : number + +c.explicitThis = m => m; +>c.explicitThis = m => m : (m: number) => number +>c.explicitThis : (this: C, m: number) => number +>c : C +>explicitThis : (this: C, m: number) => number +>m => m : (m: number) => number +>m : number +>m : number + +c.explicitProperty = m => m; +>c.explicitProperty = m => m : (m: number) => number +>c.explicitProperty : (this: { n: number; }, m: number) => number +>c : C +>explicitProperty : (this: { n: number; }, m: number) => number +>m => m : (m: number) => number +>m : number +>m : number + +// this inside lambdas refer to outer scope +// the outer-scoped lambda at top-level is still just `any` +c.explicitC = m => m + this.n; +>c.explicitC = m => m + this.n : (m: number) => any +>c.explicitC : (this: C, m: number) => number +>c : C +>explicitC : (this: C, m: number) => number +>m => m + this.n : (m: number) => any +>m : number +>m + this.n : any +>m : number +>this.n : any +>this : any +>n : any + +c.explicitThis = m => m + this.n; +>c.explicitThis = m => m + this.n : (m: number) => any +>c.explicitThis : (this: C, m: number) => number +>c : C +>explicitThis : (this: C, m: number) => number +>m => m + this.n : (m: number) => any +>m : number +>m + this.n : any +>m : number +>this.n : any +>this : any +>n : any + +c.explicitProperty = m => m + this.n; +>c.explicitProperty = m => m + this.n : (m: number) => any +>c.explicitProperty : (this: { n: number; }, m: number) => number +>c : C +>explicitProperty : (this: { n: number; }, m: number) => number +>m => m + this.n : (m: number) => any +>m : number +>m + this.n : any +>m : number +>this.n : any +>this : any +>n : any + +//NOTE: this=C here, I guess? +c.explicitThis = explicitCFunction; +>c.explicitThis = explicitCFunction : (this: C, m: number) => number +>c.explicitThis : (this: C, m: number) => number +>c : C +>explicitThis : (this: C, m: number) => number +>explicitCFunction : (this: C, m: number) => number + +c.explicitThis = function(this: C, m: number) { return this.n + m }; +>c.explicitThis = function(this: C, m: number) { return this.n + m } : (this: C, m: number) => number +>c.explicitThis : (this: C, m: number) => number +>c : C +>explicitThis : (this: C, m: number) => number +>function(this: C, m: number) { return this.n + m } : (this: C, m: number) => number +>this : C +>C : C +>m : number +>this.n + m : number +>this.n : number +>this : C +>n : number +>m : number + +// this:any compatibility +c.explicitC = function(m: number) { return this.n + m }; +>c.explicitC = function(m: number) { return this.n + m } : (this: C, m: number) => number +>c.explicitC : (this: C, m: number) => number +>c : C +>explicitC : (this: C, m: number) => number +>function(m: number) { return this.n + m } : (this: C, m: number) => number +>m : number +>this.n + m : number +>this.n : number +>this : C +>n : number +>m : number + +c.explicitProperty = function(m: number) { return this.n + m }; +>c.explicitProperty = function(m: number) { return this.n + m } : (this: { n: number; }, m: number) => number +>c.explicitProperty : (this: { n: number; }, m: number) => number +>c : C +>explicitProperty : (this: { n: number; }, m: number) => number +>function(m: number) { return this.n + m } : (this: { n: number; }, m: number) => number +>m : number +>this.n + m : number +>this.n : number +>this : { n: number; } +>n : number +>m : number + +c.explicitThis = function(m: number) { return this.n + m }; +>c.explicitThis = function(m: number) { return this.n + m } : (this: C, m: number) => number +>c.explicitThis : (this: C, m: number) => number +>c : C +>explicitThis : (this: C, m: number) => number +>function(m: number) { return this.n + m } : (this: C, m: number) => number +>m : number +>this.n + m : number +>this.n : number +>this : C +>n : number +>m : number + +c.implicitThis = function(m: number) { return this.n + m }; +>c.implicitThis = function(m: number) { return this.n + m } : (this: C, m: number) => number +>c.implicitThis : (this: C, m: number) => number +>c : C +>implicitThis : (this: C, m: number) => number +>function(m: number) { return this.n + m } : (this: C, m: number) => number +>m : number +>this.n + m : number +>this.n : number +>this : C +>n : number +>m : number + +c.implicitThis = reconstructed.implicitThis; +>c.implicitThis = reconstructed.implicitThis : (m: number) => number +>c.implicitThis : (this: C, m: number) => number +>c : C +>implicitThis : (this: C, m: number) => number +>reconstructed.implicitThis : (m: number) => number +>reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(m: number): number; } +>implicitThis : (m: number) => number + +c.explicitC = function(this: B, m: number) { return this.n + m }; +>c.explicitC = function(this: B, m: number) { return this.n + m } : (this: B, m: number) => number +>c.explicitC : (this: C, m: number) => number +>c : C +>explicitC : (this: C, m: number) => number +>function(this: B, m: number) { return this.n + m } : (this: B, m: number) => number +>this : B +>B : B +>m : number +>this.n + m : number +>this.n : number +>this : B +>n : number +>m : number + +// this:void compatibility +c.explicitVoid = n => n; +>c.explicitVoid = n => n : (n: number) => number +>c.explicitVoid : (m: number) => number +>c : C +>explicitVoid : (m: number) => number +>n => n : (n: number) => number +>n : number +>n : number + +// class-based assignability +class Base1 { +>Base1 : Base1 + + x: number; +>x : number + + public implicit(): number { return this.x; } +>implicit : (this: this) => number +>this.x : number +>this : this +>x : number + + explicit(this: Base1): number { return this.x; } +>explicit : (this: Base1) => number +>this : Base1 +>Base1 : Base1 +>this.x : number +>this : Base1 +>x : number + + static implicitStatic(): number { return this.y; } +>implicitStatic : (this: typeof Base1) => number +>this.y : number +>this : typeof Base1 +>y : number + + static explicitStatic(this: typeof Base1): number { return this.y; } +>explicitStatic : (this: typeof Base1) => number +>this : typeof Base1 +>Base1 : typeof Base1 +>this.y : number +>this : typeof Base1 +>y : number + + static y: number; +>y : number + +} +class Derived1 extends Base1 { +>Derived1 : Derived1 +>Base1 : Base1 + + y: number +>y : number +} +class Base2 { +>Base2 : Base2 + + y: number +>y : number + + implicit(): number { return this.y; } +>implicit : (this: this) => number +>this.y : number +>this : this +>y : number + + explicit(this: Base1): number { return this.x; } +>explicit : (this: Base1) => number +>this : Base1 +>Base1 : Base1 +>this.x : number +>this : Base1 +>x : number +} +class Derived2 extends Base2 { +>Derived2 : Derived2 +>Base2 : Base2 + + x: number +>x : number +} +let b1 = new Base1(); +>b1 : Base1 +>new Base1() : Base1 +>Base1 : typeof Base1 + +let b2 = new Base2(); +>b2 : Base2 +>new Base2() : Base2 +>Base2 : typeof Base2 + +let d1 = new Derived1(); +>d1 : Derived1 +>new Derived1() : Derived1 +>Derived1 : typeof Derived1 + +let d2 = new Derived2(); +>d2 : Derived2 +>new Derived2() : Derived2 +>Derived2 : typeof Derived2 + +d2.implicit = d1.implicit // ok, 'x' and 'y' in { x, y } (d assignable to f and vice versa) +>d2.implicit = d1.implicit : (this: Derived1) => number +>d2.implicit : (this: Derived2) => number +>d2 : Derived2 +>implicit : (this: Derived2) => number +>d1.implicit : (this: Derived1) => number +>d1 : Derived1 +>implicit : (this: Derived1) => number + +d1.implicit = d2.implicit // ok, 'x' and 'y' in { x, y } (f assignable to d and vice versa) +>d1.implicit = d2.implicit : (this: Derived2) => number +>d1.implicit : (this: Derived1) => number +>d1 : Derived1 +>implicit : (this: Derived1) => number +>d2.implicit : (this: Derived2) => number +>d2 : Derived2 +>implicit : (this: Derived2) => number + +// bivariance-allowed cases +d1.implicit = b2.implicit // ok, 'y' in D: { x, y } (d assignable e) +>d1.implicit = b2.implicit : (this: Base2) => number +>d1.implicit : (this: Derived1) => number +>d1 : Derived1 +>implicit : (this: Derived1) => number +>b2.implicit : (this: Base2) => number +>b2 : Base2 +>implicit : (this: Base2) => number + +d2.implicit = d1.explicit // ok, 'y' in { x, y } (c assignable to f) +>d2.implicit = d1.explicit : (this: Base1) => number +>d2.implicit : (this: Derived2) => number +>d2 : Derived2 +>implicit : (this: Derived2) => number +>d1.explicit : (this: Base1) => number +>d1 : Derived1 +>explicit : (this: Base1) => number + +b1.implicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) +>b1.implicit = d2.implicit : (this: Derived2) => number +>b1.implicit : (this: Base1) => number +>b1 : Base1 +>implicit : (this: Base1) => number +>d2.implicit : (this: Derived2) => number +>d2 : Derived2 +>implicit : (this: Derived2) => number + +b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) +>b1.explicit = d2.implicit : (this: Derived2) => number +>b1.explicit : (this: Base1) => number +>b1 : Base1 +>explicit : (this: Base1) => number +>d2.implicit : (this: Derived2) => number +>d2 : Derived2 +>implicit : (this: Derived2) => number + +////// use this-type for construction with new //// +function InterfaceThis(this: I) { +>InterfaceThis : (this: I) => void +>this : I +>I : I + + this.a = 12; +>this.a = 12 : number +>this.a : number +>this : I +>a : number +>12 : number +} +function LiteralTypeThis(this: {x: string}) { +>LiteralTypeThis : (this: { x: string; }) => void +>this : { x: string; } +>x : string + + this.x = "ok"; +>this.x = "ok" : string +>this.x : string +>this : { x: string; } +>x : string +>"ok" : string +} +function AnyThis(this: any) { +>AnyThis : () => void +>this : any + + this.x = "ok"; +>this.x = "ok" : string +>this.x : any +>this : any +>x : any +>"ok" : string +} +let interfaceThis = new InterfaceThis(); +>interfaceThis : I +>new InterfaceThis() : I +>InterfaceThis : (this: I) => void + +let literalTypeThis = new LiteralTypeThis(); +>literalTypeThis : { x: string; } +>new LiteralTypeThis() : { x: string; } +>LiteralTypeThis : (this: { x: string; }) => void + +let anyThis = new AnyThis(); +>anyThis : any +>new AnyThis() : any +>AnyThis : () => void + +//// type parameter inference //// +declare var f: { +>f : { (x: number): number; call(this: (...argArray: any[]) => U, ...argArray: any[]): U; } + + (this: void, x: number): number, +>this : void +>x : number + + call(this: (...argArray: any[]) => U, ...argArray: any[]): U; +>call : (this: (...argArray: any[]) => U, ...argArray: any[]) => U +>U : U +>this : (...argArray: any[]) => U +>argArray : any[] +>U : U +>argArray : any[] +>U : U + +}; +let n: number = f.call(12); +>n : number +>f.call(12) : number +>f.call : (this: (...argArray: any[]) => U, ...argArray: any[]) => U +>f : { (x: number): number; call(this: (...argArray: any[]) => U, ...argArray: any[]): U; } +>call : (this: (...argArray: any[]) => U, ...argArray: any[]) => U +>12 : number + +function missingTypeIsImplicitAny(this, a: number) { return a; } +>missingTypeIsImplicitAny : (a: number) => number +>this : any +>a : number +>a : number + diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt new file mode 100644 index 00000000000..49a4380977a --- /dev/null +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt @@ -0,0 +1,509 @@ +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(16,15): error TS2339: Property 'n' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(44,21): error TS2339: Property 'a' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(55,49): error TS2339: Property 'a' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(58,1): error TS2345: Argument of type 'void' is not assignable to parameter of type '{ a: number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(60,1): error TS2345: Argument of type 'void' is not assignable to parameter of type 'I'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(62,1): error TS2345: Argument of type 'void' is not assignable to parameter of type 'I'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(67,21): error TS2339: Property 'notFound' does not exist on type '{ y: number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(70,21): error TS2339: Property 'notSpecified' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(74,21): error TS2339: Property 'notSpecified' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(76,79): error TS2322: Type '{ y: number; explicitStructural: (this: { y: number; }, x: number) => number; }' is not assignable to type '{ y: number; f: (this: { y: number; }, x: number) => number; }'. + Object literal may only specify known properties, and 'explicitStructural' does not exist in type '{ y: number; f: (this: { y: number; }, x: number) => number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(77,97): error TS2322: Type '{ y: string; explicitStructural: (this: { y: number; }, x: number) => number; }' is not assignable to type '{ y: string; f: (this: { y: number; }, x: number) => number; }'. + Object literal may only specify known properties, and 'explicitStructural' does not exist in type '{ y: string; f: (this: { y: number; }, x: number) => number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(78,110): error TS2322: Type '{ wrongName: number; explicitStructural: (this: { y: number; }, x: number) => number; }' is not assignable to type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }'. + Object literal may only specify known properties, and 'explicitStructural' does not exist in type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(80,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(81,6): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(82,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(83,1): error TS2345: Argument of type '{ y: string; f: (this: { y: number; }, x: number) => number; }' is not assignable to parameter of type '{ y: number; }'. + Types of property 'y' are incompatible. + Type 'string' is not assignable to type 'number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(84,1): error TS2345: Argument of type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }' is not assignable to parameter of type '{ y: number; }'. + Property 'y' is missing in type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(87,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(88,13): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(89,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(90,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(91,16): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(92,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(93,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(94,16): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(95,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(96,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(97,20): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(98,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(101,5): error TS2322: Type '(this: { y: number; }, x: number) => number' is not assignable to type '(x: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'void' is not assignable to type '{ y: number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(124,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'C' is not assignable to type 'D'. + Property 'x' is missing in type 'C'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(125,1): error TS2322: Type '(this: { x: number; }, m: number) => number' is not assignable to type '(this: { n: number; }, m: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type '{ n: number; }' is not assignable to type '{ x: number; }'. + Property 'x' is missing in type '{ n: number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(127,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'C' is not assignable to type 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(128,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'C' is not assignable to type 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(129,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'C' is not assignable to type 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(130,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'C' is not assignable to type 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(131,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'C' is not assignable to type 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(132,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'C' is not assignable to type 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(133,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: { n: number; }, m: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type '{ n: number; }' is not assignable to type 'D'. + Property 'x' is missing in type '{ n: number; }'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(134,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: { n: number; }, m: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type '{ n: number; }' is not assignable to type 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(135,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(136,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(m: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'void' is not assignable to type 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(137,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(m: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'void' is not assignable to type 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(138,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(m: number) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'void' is not assignable to type 'D'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(146,51): error TS2339: Property 'x' does not exist on type 'typeof Base1'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(147,69): error TS2339: Property 'x' does not exist on type 'typeof Base1'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(167,1): error TS2322: Type '(this: Base2) => number' is not assignable to type '(this: Base1) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'Base1' is not assignable to type 'Base2'. + Property 'y' is missing in type 'Base1'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(168,1): error TS2322: Type '(this: Base2) => number' is not assignable to type '(this: Base1) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'Base1' is not assignable to type 'Base2'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(170,1): error TS2322: Type '(this: Base2) => number' is not assignable to type '(this: Base1) => number'. + Types of parameters 'this' and 'this' are incompatible. + Type 'Base1' is not assignable to type 'Base2'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(179,16): error TS2671: A function that is called with the 'new' keyword cannot have a 'this' type that is void. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(180,24): error TS2671: A function that is called with the 'new' keyword cannot have a 'this' type that is void. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(184,30): error TS2332: 'this' cannot be referenced in current location. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(185,26): error TS1003: Identifier expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(185,30): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(185,57): error TS2339: Property 'n' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(186,20): error TS2370: A rest parameter must be of an array type. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(186,23): error TS1003: Identifier expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(186,27): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(186,54): error TS2339: Property 'n' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(187,23): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(187,24): error TS1138: Parameter declaration expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(187,51): error TS2339: Property 'n' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(188,28): error TS1003: Identifier expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(188,32): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(188,59): error TS2339: Property 'n' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,30): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,32): error TS1138: Parameter declaration expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,39): error TS1005: ';' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,40): error TS1128: Declaration or statement expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,42): error TS2304: Cannot find name 'number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,49): error TS1005: ';' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,1): error TS7027: Unreachable code detected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,29): error TS2304: Cannot find name 'm'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,32): error TS1005: ';' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,35): error TS2304: Cannot find name 'm'. + + +==== tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts (75 errors) ==== + class C { + n: number; + explicitThis(this: this, m: number): number { + return this.n + m; + } + implicitThis(m: number): number { + return this.n + m; + } + explicitC(this: C, m: number): number { + return this.n + m; + } + explicitProperty(this: {n: number}, m: number): number { + return this.n + m; + } + explicitVoid(this: void, m: number): number { + return this.n + m; // 'n' doesn't exist on type 'void'. + ~ +!!! error TS2339: Property 'n' does not exist on type 'void'. + } + } + class D { + x: number; + explicitThis(this: this, m: number): number { + return this.x + m; + } + explicitD(this: D, m: number): number { + return this.x + m; + } + implicitD(m: number): number { + return this.x + m; + } + } + interface I { + a: number; + explicitVoid1(this: void): number; + explicitVoid2(this: void): number; + explicitStructural(this: {a: number}): number; + explicitInterface(this: I): number; + explicitThis(this: this): number; // TODO: Allow `this` types for interfaces + implicitMethod(): number; + implicitFunction: () => number; + } + let impl: I = { + a: 12, + explicitVoid1() { + return this.a; // error, no 'a' in 'void' + ~ +!!! error TS2339: Property 'a' does not exist on type 'void'. + }, + explicitVoid2: () => this.a, // ok, `this:any` because it refers to an outer object + explicitStructural: () => 12, + explicitInterface: () => 12, + explicitThis() { + return this.a; + }, + implicitMethod() { + return this.a; // ok, I.a: number + }, + implicitFunction: function () { return this.a; } // TODO: error 'a' not found in 'void' + ~ +!!! error TS2339: Property 'a' does not exist on type 'void'. + } + let implExplicitStructural = impl.explicitStructural; + implExplicitStructural(); // error, no 'a' in 'void' + ~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type 'void' is not assignable to parameter of type '{ a: number; }'. + let implExplicitInterface = impl.explicitInterface; + implExplicitInterface(); // error, no 'a' in 'void' + ~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type 'void' is not assignable to parameter of type 'I'. + let implImplicitMethod = impl.implicitMethod; + implImplicitMethod(); // error, no 'a' in 'void' + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type 'void' is not assignable to parameter of type 'I'. + function explicitStructural(this: { y: number }, x: number): number { + return x + this.y; + } + function propertyName(this: { y: number }, x: number): number { + return x + this.notFound; + ~~~~~~~~ +!!! error TS2339: Property 'notFound' does not exist on type '{ y: number; }'. + } + function voidThisSpecified(this: void, x: number): number { + return x + this.notSpecified; + ~~~~~~~~~~~~ +!!! error TS2339: Property 'notSpecified' does not exist on type 'void'. + } + function noThisSpecified(x: number): number { + // this:void unless loose-this is on + return x + this.notSpecified; + ~~~~~~~~~~~~ +!!! error TS2339: Property 'notSpecified' does not exist on type 'void'. + } + let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, explicitStructural }; + ~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ y: number; explicitStructural: (this: { y: number; }, x: number) => number; }' is not assignable to type '{ y: number; f: (this: { y: number; }, x: number) => number; }'. +!!! error TS2322: Object literal may only specify known properties, and 'explicitStructural' does not exist in type '{ y: number; f: (this: { y: number; }, x: number) => number; }'. + let wrongPropertyType: {y: string, f: (this: { y: number }, x: number) => number} = { y: 'foo', explicitStructural }; + ~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ y: string; explicitStructural: (this: { y: number; }, x: number) => number; }' is not assignable to type '{ y: string; f: (this: { y: number; }, x: number) => number; }'. +!!! error TS2322: Object literal may only specify known properties, and 'explicitStructural' does not exist in type '{ y: string; f: (this: { y: number; }, x: number) => number; }'. + let wrongPropertyName: {wrongName: number, f: (this: { y: number }, x: number) => number} = { wrongName: 12, explicitStructural }; + ~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ wrongName: number; explicitStructural: (this: { y: number; }, x: number) => number; }' is not assignable to type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }'. +!!! error TS2322: Object literal may only specify known properties, and 'explicitStructural' does not exist in type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }'. + + ok.f(); // not enough arguments + ~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + ok.f('wrong type'); + ~~~~~~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. + ok.f(13, 'too many arguments'); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + wrongPropertyType.f(13); + ~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '{ y: string; f: (this: { y: number; }, x: number) => number; }' is not assignable to parameter of type '{ y: number; }'. +!!! error TS2345: Types of property 'y' are incompatible. +!!! error TS2345: Type 'string' is not assignable to type 'number'. + wrongPropertyName.f(13); + ~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }' is not assignable to parameter of type '{ y: number; }'. +!!! error TS2345: Property 'y' is missing in type '{ wrongName: number; f: (this: { y: number; }, x: number) => number; }'. + + let c = new C(); + c.explicitC(); // not enough arguments + ~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + c.explicitC('wrong type'); + ~~~~~~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. + c.explicitC(13, 'too many arguments'); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + c.explicitThis(); // not enough arguments + ~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + c.explicitThis('wrong type 2'); + ~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. + c.explicitThis(14, 'too many arguments 2'); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + c.implicitThis(); // not enough arguments + ~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + c.implicitThis('wrong type 2'); + ~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. + c.implicitThis(14, 'too many arguments 2'); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + c.explicitProperty(); // not enough arguments + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + c.explicitProperty('wrong type 3'); + ~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. + c.explicitProperty(15, 'too many arguments 3'); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + + // oops, this triggers contextual typing, which needs to be updated to understand that =>'s `this` is void. + let specifiedToImplicitVoid: (x: number) => number = explicitStructural; + ~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: { y: number; }, x: number) => number' is not assignable to type '(x: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'void' is not assignable to type '{ y: number; }'. + + let reconstructed: { + n: number, + explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. + implicitThis(m: number): number, + explicitC(this: C, m: number): number, + explicitProperty: (this: {n : number}, m: number) => number, + explicitVoid(this: void, m: number): number, + } = { + n: 12, + explicitThis: c.explicitThis, + implicitThis: c.implicitThis, // error not assignable -- c.this:c not assignable to this:void. + explicitC: c.explicitC, + explicitProperty: c.explicitProperty, + explicitVoid: c.explicitVoid + };; + + // lambdas have this: void for assignability purposes (and this unbound (free) for body checking) + let d = new D(); + let explicitXProperty: (this: { x: number }, m: number) => number; + + // from differing object types + c.explicitC = function(this: D, m: number) { return this.x + m }; + ~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'C' is not assignable to type 'D'. +!!! error TS2322: Property 'x' is missing in type 'C'. + c.explicitProperty = explicitXProperty; + ~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: { x: number; }, m: number) => number' is not assignable to type '(this: { n: number; }, m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type '{ n: number; }' is not assignable to type '{ x: number; }'. +!!! error TS2322: Property 'x' is missing in type '{ n: number; }'. + + c.explicitC = d.implicitD; + ~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'C' is not assignable to type 'D'. + c.explicitC = d.explicitD; + ~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'C' is not assignable to type 'D'. + c.explicitC = d.explicitThis; + ~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'C' is not assignable to type 'D'. + c.explicitThis = d.implicitD; + ~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'C' is not assignable to type 'D'. + c.explicitThis = d.explicitD; + ~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'C' is not assignable to type 'D'. + c.explicitThis = d.explicitThis; + ~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'C' is not assignable to type 'D'. + c.explicitProperty = d.explicitD; + ~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: { n: number; }, m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type '{ n: number; }' is not assignable to type 'D'. +!!! error TS2322: Property 'x' is missing in type '{ n: number; }'. + c.explicitProperty = d.implicitD; + ~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: { n: number; }, m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type '{ n: number; }' is not assignable to type 'D'. + c.explicitThis = d.explicitThis; + ~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. + c.explicitVoid = d.implicitD; + ~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'void' is not assignable to type 'D'. + c.explicitVoid = d.explicitD; + ~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'void' is not assignable to type 'D'. + c.explicitVoid = d.explicitThis; + ~~~~~~~~~~~~~~ +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(m: number) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'void' is not assignable to type 'D'. + + /// class-based implicit assignability (with inheritance!) /// + + class Base1 { + x: number + public implicit(): number { return this.x; } + explicit(this: Base1): number { return this.x; } + static implicitStatic(): number { return this.x; } + ~ +!!! error TS2339: Property 'x' does not exist on type 'typeof Base1'. + static explicitStatic(this: typeof Base1): number { return this.x; } + ~ +!!! error TS2339: Property 'x' does not exist on type 'typeof Base1'. + } + class Derived1 extends Base1 { + y: number + } + class Base2 { + y: number + implicit(): number { return this.y; } + explicit(this: Base1): number { return this.x; } + } + class Derived2 extends Base2 { + x: number + } + + + let b1 = new Base1(); + let d1 = new Derived1(); + let b2 = new Base2(); + let d2 = new Derived2(); + + b1.implicit = b2.implicit // error, 'this.y' not in C: { x } (c assignable to e) + ~~~~~~~~~~~ +!!! error TS2322: Type '(this: Base2) => number' is not assignable to type '(this: Base1) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'Base1' is not assignable to type 'Base2'. +!!! error TS2322: Property 'y' is missing in type 'Base1'. + b1.explicit = b2.implicit // error, 'y' not in C: { x } (c assignable to e) + ~~~~~~~~~~~ +!!! error TS2322: Type '(this: Base2) => number' is not assignable to type '(this: Base1) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'Base1' is not assignable to type 'Base2'. + + d1.explicit = b2.implicit // error, 'y' not in C: { x } (c assignable to e) + ~~~~~~~~~~~ +!!! error TS2322: Type '(this: Base2) => number' is not assignable to type '(this: Base1) => number'. +!!! error TS2322: Types of parameters 'this' and 'this' are incompatible. +!!! error TS2322: Type 'Base1' is not assignable to type 'Base2'. + + ////// use this-type for construction with new //// + function VoidThis(this: void) { + + } + function ImplicitVoidThis() { + + } + let voidThis = new VoidThis(); + ~~~~~~~~~~~~~~ +!!! error TS2671: A function that is called with the 'new' keyword cannot have a 'this' type that is void. + let implicitVoidThis = new ImplicitVoidThis(); + ~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2671: A function that is called with the 'new' keyword cannot have a 'this' type that is void. + + + ///// parse errors ///// + function notFirst(a: number, this: C): number { return this.n; } + ~~~~~~~ +!!! error TS2332: 'this' cannot be referenced in current location. + function modifiers(async this: C): number { return this.n; } + ~~~~ +!!! error TS1003: Identifier expected. + ~ +!!! error TS1005: ',' expected. + ~ +!!! error TS2339: Property 'n' does not exist on type 'void'. + function restParam(...this: C): number { return this.n; } + ~~~~~~~ +!!! error TS2370: A rest parameter must be of an array type. + ~~~~ +!!! error TS1003: Identifier expected. + ~ +!!! error TS1005: ',' expected. + ~ +!!! error TS2339: Property 'n' does not exist on type 'void'. + function optional(this?: C): number { return this.n; } + ~ +!!! error TS1005: ',' expected. + ~ +!!! error TS1138: Parameter declaration expected. + ~ +!!! error TS2339: Property 'n' does not exist on type 'void'. + function decorated(@deco() this: C): number { return this.n; } + ~~~~ +!!! error TS1003: Identifier expected. + ~ +!!! error TS1005: ',' expected. + ~ +!!! error TS2339: Property 'n' does not exist on type 'void'. + function initializer(this: C = new C()): number { return this.n; } + ~ +!!! error TS1005: ',' expected. + ~~~ +!!! error TS1138: Parameter declaration expected. + ~ +!!! error TS1005: ';' expected. + ~ +!!! error TS1128: Declaration or statement expected. + ~~~~~~ +!!! error TS2304: Cannot find name 'number'. + ~ +!!! error TS1005: ';' expected. + + // can't name parameters 'this' in a lambda. + c.explicitProperty = (this, m) => m + this.n; + ~ +!!! error TS7027: Unreachable code detected. + ~ +!!! error TS2304: Cannot find name 'm'. + ~~ +!!! error TS1005: ';' expected. + ~ +!!! error TS2304: Cannot find name 'm'. + \ No newline at end of file diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.js b/tests/baselines/reference/thisTypeInFunctionsNegative.js new file mode 100644 index 00000000000..43d83daef0d --- /dev/null +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.js @@ -0,0 +1,386 @@ +//// [thisTypeInFunctionsNegative.ts] +class C { + n: number; + explicitThis(this: this, m: number): number { + return this.n + m; + } + implicitThis(m: number): number { + return this.n + m; + } + explicitC(this: C, m: number): number { + return this.n + m; + } + explicitProperty(this: {n: number}, m: number): number { + return this.n + m; + } + explicitVoid(this: void, m: number): number { + return this.n + m; // 'n' doesn't exist on type 'void'. + } +} +class D { + x: number; + explicitThis(this: this, m: number): number { + return this.x + m; + } + explicitD(this: D, m: number): number { + return this.x + m; + } + implicitD(m: number): number { + return this.x + m; + } +} +interface I { + a: number; + explicitVoid1(this: void): number; + explicitVoid2(this: void): number; + explicitStructural(this: {a: number}): number; + explicitInterface(this: I): number; + explicitThis(this: this): number; // TODO: Allow `this` types for interfaces + implicitMethod(): number; + implicitFunction: () => number; +} +let impl: I = { + a: 12, + explicitVoid1() { + return this.a; // error, no 'a' in 'void' + }, + explicitVoid2: () => this.a, // ok, `this:any` because it refers to an outer object + explicitStructural: () => 12, + explicitInterface: () => 12, + explicitThis() { + return this.a; + }, + implicitMethod() { + return this.a; // ok, I.a: number + }, + implicitFunction: function () { return this.a; } // TODO: error 'a' not found in 'void' +} +let implExplicitStructural = impl.explicitStructural; +implExplicitStructural(); // error, no 'a' in 'void' +let implExplicitInterface = impl.explicitInterface; +implExplicitInterface(); // error, no 'a' in 'void' +let implImplicitMethod = impl.implicitMethod; +implImplicitMethod(); // error, no 'a' in 'void' +function explicitStructural(this: { y: number }, x: number): number { + return x + this.y; +} +function propertyName(this: { y: number }, x: number): number { + return x + this.notFound; +} +function voidThisSpecified(this: void, x: number): number { + return x + this.notSpecified; +} +function noThisSpecified(x: number): number { + // this:void unless loose-this is on + return x + this.notSpecified; +} +let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, explicitStructural }; +let wrongPropertyType: {y: string, f: (this: { y: number }, x: number) => number} = { y: 'foo', explicitStructural }; +let wrongPropertyName: {wrongName: number, f: (this: { y: number }, x: number) => number} = { wrongName: 12, explicitStructural }; + +ok.f(); // not enough arguments +ok.f('wrong type'); +ok.f(13, 'too many arguments'); +wrongPropertyType.f(13); +wrongPropertyName.f(13); + +let c = new C(); +c.explicitC(); // not enough arguments +c.explicitC('wrong type'); +c.explicitC(13, 'too many arguments'); +c.explicitThis(); // not enough arguments +c.explicitThis('wrong type 2'); +c.explicitThis(14, 'too many arguments 2'); +c.implicitThis(); // not enough arguments +c.implicitThis('wrong type 2'); +c.implicitThis(14, 'too many arguments 2'); +c.explicitProperty(); // not enough arguments +c.explicitProperty('wrong type 3'); +c.explicitProperty(15, 'too many arguments 3'); + +// oops, this triggers contextual typing, which needs to be updated to understand that =>'s `this` is void. +let specifiedToImplicitVoid: (x: number) => number = explicitStructural; + +let reconstructed: { + n: number, + explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. + implicitThis(m: number): number, + explicitC(this: C, m: number): number, + explicitProperty: (this: {n : number}, m: number) => number, + explicitVoid(this: void, m: number): number, +} = { + n: 12, + explicitThis: c.explicitThis, + implicitThis: c.implicitThis, // error not assignable -- c.this:c not assignable to this:void. + explicitC: c.explicitC, + explicitProperty: c.explicitProperty, + explicitVoid: c.explicitVoid +};; + +// lambdas have this: void for assignability purposes (and this unbound (free) for body checking) +let d = new D(); +let explicitXProperty: (this: { x: number }, m: number) => number; + +// from differing object types +c.explicitC = function(this: D, m: number) { return this.x + m }; +c.explicitProperty = explicitXProperty; + +c.explicitC = d.implicitD; +c.explicitC = d.explicitD; +c.explicitC = d.explicitThis; +c.explicitThis = d.implicitD; +c.explicitThis = d.explicitD; +c.explicitThis = d.explicitThis; +c.explicitProperty = d.explicitD; +c.explicitProperty = d.implicitD; +c.explicitThis = d.explicitThis; +c.explicitVoid = d.implicitD; +c.explicitVoid = d.explicitD; +c.explicitVoid = d.explicitThis; + +/// class-based implicit assignability (with inheritance!) /// + +class Base1 { + x: number + public implicit(): number { return this.x; } + explicit(this: Base1): number { return this.x; } + static implicitStatic(): number { return this.x; } + static explicitStatic(this: typeof Base1): number { return this.x; } +} +class Derived1 extends Base1 { + y: number +} +class Base2 { + y: number + implicit(): number { return this.y; } + explicit(this: Base1): number { return this.x; } +} +class Derived2 extends Base2 { + x: number +} + + +let b1 = new Base1(); +let d1 = new Derived1(); +let b2 = new Base2(); +let d2 = new Derived2(); + +b1.implicit = b2.implicit // error, 'this.y' not in C: { x } (c assignable to e) +b1.explicit = b2.implicit // error, 'y' not in C: { x } (c assignable to e) + +d1.explicit = b2.implicit // error, 'y' not in C: { x } (c assignable to e) + +////// use this-type for construction with new //// +function VoidThis(this: void) { + +} +function ImplicitVoidThis() { + +} +let voidThis = new VoidThis(); +let implicitVoidThis = new ImplicitVoidThis(); + + +///// parse errors ///// +function notFirst(a: number, this: C): number { return this.n; } +function modifiers(async this: C): number { return this.n; } +function restParam(...this: C): number { return this.n; } +function optional(this?: C): number { return this.n; } +function decorated(@deco() this: C): number { return this.n; } +function initializer(this: C = new C()): number { return this.n; } + +// can't name parameters 'this' in a lambda. +c.explicitProperty = (this, m) => m + this.n; + + +//// [thisTypeInFunctionsNegative.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; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var _this = this; +var C = (function () { + function C() { + } + C.prototype.explicitThis = function (m) { + return this.n + m; + }; + C.prototype.implicitThis = function (m) { + return this.n + m; + }; + C.prototype.explicitC = function (m) { + return this.n + m; + }; + C.prototype.explicitProperty = function (m) { + return this.n + m; + }; + C.prototype.explicitVoid = function (m) { + return this.n + m; // 'n' doesn't exist on type 'void'. + }; + return C; +}()); +var D = (function () { + function D() { + } + D.prototype.explicitThis = function (m) { + return this.x + m; + }; + D.prototype.explicitD = function (m) { + return this.x + m; + }; + D.prototype.implicitD = function (m) { + return this.x + m; + }; + return D; +}()); +var impl = { + a: 12, + explicitVoid1: function () { + return this.a; // error, no 'a' in 'void' + }, + explicitVoid2: function () { return _this.a; }, + explicitStructural: function () { return 12; }, + explicitInterface: function () { return 12; }, + explicitThis: function () { + return this.a; + }, + implicitMethod: function () { + return this.a; // ok, I.a: number + }, + implicitFunction: function () { return this.a; } // TODO: error 'a' not found in 'void' +}; +var implExplicitStructural = impl.explicitStructural; +implExplicitStructural(); // error, no 'a' in 'void' +var implExplicitInterface = impl.explicitInterface; +implExplicitInterface(); // error, no 'a' in 'void' +var implImplicitMethod = impl.implicitMethod; +implImplicitMethod(); // error, no 'a' in 'void' +function explicitStructural(x) { + return x + this.y; +} +function propertyName(x) { + return x + this.notFound; +} +function voidThisSpecified(x) { + return x + this.notSpecified; +} +function noThisSpecified(x) { + // this:void unless loose-this is on + return x + this.notSpecified; +} +var ok = { y: 12, explicitStructural: explicitStructural }; +var wrongPropertyType = { y: 'foo', explicitStructural: explicitStructural }; +var wrongPropertyName = { wrongName: 12, explicitStructural: explicitStructural }; +ok.f(); // not enough arguments +ok.f('wrong type'); +ok.f(13, 'too many arguments'); +wrongPropertyType.f(13); +wrongPropertyName.f(13); +var c = new C(); +c.explicitC(); // not enough arguments +c.explicitC('wrong type'); +c.explicitC(13, 'too many arguments'); +c.explicitThis(); // not enough arguments +c.explicitThis('wrong type 2'); +c.explicitThis(14, 'too many arguments 2'); +c.implicitThis(); // not enough arguments +c.implicitThis('wrong type 2'); +c.implicitThis(14, 'too many arguments 2'); +c.explicitProperty(); // not enough arguments +c.explicitProperty('wrong type 3'); +c.explicitProperty(15, 'too many arguments 3'); +// oops, this triggers contextual typing, which needs to be updated to understand that =>'s `this` is void. +var specifiedToImplicitVoid = explicitStructural; +var reconstructed = { + n: 12, + explicitThis: c.explicitThis, + implicitThis: c.implicitThis, + explicitC: c.explicitC, + explicitProperty: c.explicitProperty, + explicitVoid: c.explicitVoid +}; +; +// lambdas have this: void for assignability purposes (and this unbound (free) for body checking) +var d = new D(); +var explicitXProperty; +// from differing object types +c.explicitC = function (m) { return this.x + m; }; +c.explicitProperty = explicitXProperty; +c.explicitC = d.implicitD; +c.explicitC = d.explicitD; +c.explicitC = d.explicitThis; +c.explicitThis = d.implicitD; +c.explicitThis = d.explicitD; +c.explicitThis = d.explicitThis; +c.explicitProperty = d.explicitD; +c.explicitProperty = d.implicitD; +c.explicitThis = d.explicitThis; +c.explicitVoid = d.implicitD; +c.explicitVoid = d.explicitD; +c.explicitVoid = d.explicitThis; +/// class-based implicit assignability (with inheritance!) /// +var Base1 = (function () { + function Base1() { + } + Base1.prototype.implicit = function () { return this.x; }; + Base1.prototype.explicit = function () { return this.x; }; + Base1.implicitStatic = function () { return this.x; }; + Base1.explicitStatic = function () { return this.x; }; + return Base1; +}()); +var Derived1 = (function (_super) { + __extends(Derived1, _super); + function Derived1() { + _super.apply(this, arguments); + } + return Derived1; +}(Base1)); +var Base2 = (function () { + function Base2() { + } + Base2.prototype.implicit = function () { return this.y; }; + Base2.prototype.explicit = function () { return this.x; }; + return Base2; +}()); +var Derived2 = (function (_super) { + __extends(Derived2, _super); + function Derived2() { + _super.apply(this, arguments); + } + return Derived2; +}(Base2)); +var b1 = new Base1(); +var d1 = new Derived1(); +var b2 = new Base2(); +var d2 = new Derived2(); +b1.implicit = b2.implicit; // error, 'this.y' not in C: { x } (c assignable to e) +b1.explicit = b2.implicit; // error, 'y' not in C: { x } (c assignable to e) +d1.explicit = b2.implicit; // error, 'y' not in C: { x } (c assignable to e) +////// use this-type for construction with new //// +function VoidThis() { +} +function ImplicitVoidThis() { +} +var voidThis = new VoidThis(); +var implicitVoidThis = new ImplicitVoidThis(); +///// parse errors ///// +function notFirst(a, this) { return this.n; } +function modifiers(, C) { + if ( === void 0) { = this; } + return this.n; +} +function restParam(, C) { return this.n; } +function optional(C) { return this.n; } +function decorated(, C) { + if ( === void 0) { = this; } + return this.n; +} +new C(); +number; +{ + return this.n; +} +// can't name parameters 'this' in a lambda. +c.explicitProperty = (this, m); +m + this.n; diff --git a/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts new file mode 100644 index 00000000000..34d1ebd4a8e --- /dev/null +++ b/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts @@ -0,0 +1,34 @@ +interface I { + explicitThis(this: this, m: number): number; +} +interface Unused { + implicitNoThis(m: number): number; +} +class C implements I { + n: number; + explicitThis(this: this, m: number): number { + return this.n + m; + } + implicitThis(m: number): number { + return this.n + m; + } + explicitVoid(this: void, m: number): number { + return m + 1; + } +} +let c = new C(); +c.explicitVoid = c.explicitThis; // error, 'void' is missing everything +let o = { + explicitThis: function (m) { return m }, + implicitThis(m: number): number { return m } +}; +let i: I = o; +let x = i.explicitThis; +let n = x(12); // callee:void doesn't match this:I +let u: Unused; +let y = u.implicitNoThis; +n = y(12); // ok, callee:void matches this:any +c.explicitVoid = c.implicitThis // ok, implicitThis(this:any) +o.implicitThis = c.implicitThis; // ok, implicitThis(this:any) +o.implicitThis = c.explicitThis; // ok, implicitThis(this:any) is assignable to explicitThis(this: this) +o.implicitThis = i.explicitThis; diff --git a/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts new file mode 100644 index 00000000000..623c880d339 --- /dev/null +++ b/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts @@ -0,0 +1,209 @@ +// @strictThis: true +// body checking +class C { + n: number; + explicitThis(this: this, m: number): number { + return this.n + m; + } + implicitThis(m: number): number { + return this.n + m; + } + explicitC(this: C, m: number): number { + return this.n + m; + } + explicitProperty(this: {n: number}, m: number): number { + return this.n + m; + } + explicitVoid(this: void, m: number): number { + return m + 1; + } +} +class D extends C { } +class B { + n: number; +} +interface I { + a: number; + explicitVoid1(this: void): number; + explicitVoid2(this: void): number; + explicitStructural(this: {a: number}): number; + explicitInterface(this: I): number; + explicitThis(this: this): number; + implicitMethod(): number; + implicitFunction: () => number; +} +function explicitStructural(this: { y: number }, x: number): number { + return x + this.y; +} +function justThis(this: { y: number }): number { + return this.y; +} +function implicitThis(n: number): number { + return 12; +} +let impl: I = { + a: 12, + explicitVoid2: () => this.a, // ok, this: any because it refers to some outer object (window?) + explicitVoid1() { return 12; }, + explicitStructural() { + return this.a; + }, + explicitInterface() { + return this.a; + }, + explicitThis() { + return this.a; + }, + implicitMethod() { + return this.a; + }, + implicitFunction: () => this.a, // ok, this: any because it refers to some outer object (window?) +} +impl.explicitVoid1 = function () { return 12; }; +impl.explicitVoid2 = () => 12; +impl.explicitStructural = function() { return this.a; }; +impl.explicitInterface = function() { return this.a; }; +impl.explicitStructural = () => 12; +impl.explicitInterface = () => 12; +impl.explicitThis = function () { return this.a; }; +impl.implicitMethod = function () { return this.a; }; +impl.implicitMethod = () => 12; +impl.implicitFunction = () => this.a; // ok, this: any because it refers to some outer object (window?) +// parameter checking +let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, f: explicitStructural }; +let implicitAnyOk: {notSpecified: number, f: (x: number) => number} = { notSpecified: 12, f: implicitThis }; +ok.f(13); +implicitThis(12); +implicitAnyOk.f(12); + +let c = new C(); +let d = new D(); +let ripped = c.explicitC; +c.explicitC(12); +c.explicitProperty(12); +c.explicitThis(12); +c.implicitThis(12); +d.explicitC(12); +d.explicitProperty(12); +d.explicitThis(12); +d.implicitThis(12); +let reconstructed: { + n: number, + explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. + implicitThis(m: number): number, + explicitC(this: C, m: number): number, + explicitProperty: (this: {n : number}, m: number) => number, + explicitVoid(this: void, m: number): number, +} = { + n: 12, + explicitThis: c.explicitThis, + implicitThis: c.implicitThis, + explicitC: c.explicitC, + explicitProperty: c.explicitProperty, + explicitVoid: c.explicitVoid +}; +reconstructed.explicitProperty(11); +reconstructed.implicitThis(11); + +// assignment checking +let unboundToSpecified: (this: { y: number }, x: number) => number = x => x + this.y; // ok, this:any +let specifiedToSpecified: (this: {y: number}, x: number) => number = explicitStructural; +let anyToSpecified: (this: { y: number }, x: number) => number = function(x: number): number { return x + 12; }; + +let unspecifiedLambda: (x: number) => number = x => x + 12; +let specifiedLambda: (this: void, x: number) => number = x => x + 12; +let unspecifiedLambdaToSpecified: (this: {y: number}, x: number) => number = unspecifiedLambda; +let specifiedLambdaToSpecified: (this: {y: number}, x: number) => number = specifiedLambda; + + +let explicitCFunction: (this: C, m: number) => number; +let explicitPropertyFunction: (this: {n: number}, m: number) => number; +c.explicitC = explicitCFunction; +c.explicitC = function(this: C, m: number) { return this.n + m }; +c.explicitProperty = explicitPropertyFunction; +c.explicitProperty = function(this: {n: number}, m: number) { return this.n + m }; +c.explicitProperty = reconstructed.explicitProperty; + +// lambdas are assignable to anything +c.explicitC = m => m; +c.explicitThis = m => m; +c.explicitProperty = m => m; + +// this inside lambdas refer to outer scope +// the outer-scoped lambda at top-level is still just `any` +c.explicitC = m => m + this.n; +c.explicitThis = m => m + this.n; +c.explicitProperty = m => m + this.n; + +//NOTE: this=C here, I guess? +c.explicitThis = explicitCFunction; +c.explicitThis = function(this: C, m: number) { return this.n + m }; + +// this:any compatibility +c.explicitC = function(m: number) { return this.n + m }; +c.explicitProperty = function(m: number) { return this.n + m }; +c.explicitThis = function(m: number) { return this.n + m }; +c.implicitThis = function(m: number) { return this.n + m }; +c.implicitThis = reconstructed.implicitThis; + +c.explicitC = function(this: B, m: number) { return this.n + m }; + +// this:void compatibility +c.explicitVoid = n => n; + +// class-based assignability +class Base1 { + x: number; + public implicit(): number { return this.x; } + explicit(this: Base1): number { return this.x; } + static implicitStatic(): number { return this.y; } + static explicitStatic(this: typeof Base1): number { return this.y; } + static y: number; + +} +class Derived1 extends Base1 { + y: number +} +class Base2 { + y: number + implicit(): number { return this.y; } + explicit(this: Base1): number { return this.x; } +} +class Derived2 extends Base2 { + x: number +} +let b1 = new Base1(); +let b2 = new Base2(); +let d1 = new Derived1(); +let d2 = new Derived2(); +d2.implicit = d1.implicit // ok, 'x' and 'y' in { x, y } (d assignable to f and vice versa) +d1.implicit = d2.implicit // ok, 'x' and 'y' in { x, y } (f assignable to d and vice versa) + +// bivariance-allowed cases +d1.implicit = b2.implicit // ok, 'y' in D: { x, y } (d assignable e) +d2.implicit = d1.explicit // ok, 'y' in { x, y } (c assignable to f) +b1.implicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) +b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) + +////// use this-type for construction with new //// +function InterfaceThis(this: I) { + this.a = 12; +} +function LiteralTypeThis(this: {x: string}) { + this.x = "ok"; +} +function AnyThis(this: any) { + this.x = "ok"; +} +let interfaceThis = new InterfaceThis(); +let literalTypeThis = new LiteralTypeThis(); +let anyThis = new AnyThis(); + +//// type parameter inference //// +declare var f: { + (this: void, x: number): number, + call(this: (...argArray: any[]) => U, ...argArray: any[]): U; +}; +let n: number = f.call(12); + +function missingTypeIsImplicitAny(this, a: number) { return a; } \ No newline at end of file diff --git a/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts b/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts new file mode 100644 index 00000000000..3fba9ad8a73 --- /dev/null +++ b/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts @@ -0,0 +1,193 @@ +// @strictThis: true +class C { + n: number; + explicitThis(this: this, m: number): number { + return this.n + m; + } + implicitThis(m: number): number { + return this.n + m; + } + explicitC(this: C, m: number): number { + return this.n + m; + } + explicitProperty(this: {n: number}, m: number): number { + return this.n + m; + } + explicitVoid(this: void, m: number): number { + return this.n + m; // 'n' doesn't exist on type 'void'. + } +} +class D { + x: number; + explicitThis(this: this, m: number): number { + return this.x + m; + } + explicitD(this: D, m: number): number { + return this.x + m; + } + implicitD(m: number): number { + return this.x + m; + } +} +interface I { + a: number; + explicitVoid1(this: void): number; + explicitVoid2(this: void): number; + explicitStructural(this: {a: number}): number; + explicitInterface(this: I): number; + explicitThis(this: this): number; // TODO: Allow `this` types for interfaces + implicitMethod(): number; + implicitFunction: () => number; +} +let impl: I = { + a: 12, + explicitVoid1() { + return this.a; // error, no 'a' in 'void' + }, + explicitVoid2: () => this.a, // ok, `this:any` because it refers to an outer object + explicitStructural: () => 12, + explicitInterface: () => 12, + explicitThis() { + return this.a; + }, + implicitMethod() { + return this.a; // ok, I.a: number + }, + implicitFunction: function () { return this.a; } // TODO: error 'a' not found in 'void' +} +let implExplicitStructural = impl.explicitStructural; +implExplicitStructural(); // error, no 'a' in 'void' +let implExplicitInterface = impl.explicitInterface; +implExplicitInterface(); // error, no 'a' in 'void' +let implImplicitMethod = impl.implicitMethod; +implImplicitMethod(); // error, no 'a' in 'void' +function explicitStructural(this: { y: number }, x: number): number { + return x + this.y; +} +function propertyName(this: { y: number }, x: number): number { + return x + this.notFound; +} +function voidThisSpecified(this: void, x: number): number { + return x + this.notSpecified; +} +function noThisSpecified(x: number): number { + // this:void unless loose-this is on + return x + this.notSpecified; +} +let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, explicitStructural }; +let wrongPropertyType: {y: string, f: (this: { y: number }, x: number) => number} = { y: 'foo', explicitStructural }; +let wrongPropertyName: {wrongName: number, f: (this: { y: number }, x: number) => number} = { wrongName: 12, explicitStructural }; + +ok.f(); // not enough arguments +ok.f('wrong type'); +ok.f(13, 'too many arguments'); +wrongPropertyType.f(13); +wrongPropertyName.f(13); + +let c = new C(); +c.explicitC(); // not enough arguments +c.explicitC('wrong type'); +c.explicitC(13, 'too many arguments'); +c.explicitThis(); // not enough arguments +c.explicitThis('wrong type 2'); +c.explicitThis(14, 'too many arguments 2'); +c.implicitThis(); // not enough arguments +c.implicitThis('wrong type 2'); +c.implicitThis(14, 'too many arguments 2'); +c.explicitProperty(); // not enough arguments +c.explicitProperty('wrong type 3'); +c.explicitProperty(15, 'too many arguments 3'); + +// oops, this triggers contextual typing, which needs to be updated to understand that =>'s `this` is void. +let specifiedToImplicitVoid: (x: number) => number = explicitStructural; + +let reconstructed: { + n: number, + explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. + implicitThis(m: number): number, + explicitC(this: C, m: number): number, + explicitProperty: (this: {n : number}, m: number) => number, + explicitVoid(this: void, m: number): number, +} = { + n: 12, + explicitThis: c.explicitThis, + implicitThis: c.implicitThis, // error not assignable -- c.this:c not assignable to this:void. + explicitC: c.explicitC, + explicitProperty: c.explicitProperty, + explicitVoid: c.explicitVoid +};; + +// lambdas have this: void for assignability purposes (and this unbound (free) for body checking) +let d = new D(); +let explicitXProperty: (this: { x: number }, m: number) => number; + +// from differing object types +c.explicitC = function(this: D, m: number) { return this.x + m }; +c.explicitProperty = explicitXProperty; + +c.explicitC = d.implicitD; +c.explicitC = d.explicitD; +c.explicitC = d.explicitThis; +c.explicitThis = d.implicitD; +c.explicitThis = d.explicitD; +c.explicitThis = d.explicitThis; +c.explicitProperty = d.explicitD; +c.explicitProperty = d.implicitD; +c.explicitThis = d.explicitThis; +c.explicitVoid = d.implicitD; +c.explicitVoid = d.explicitD; +c.explicitVoid = d.explicitThis; + +/// class-based implicit assignability (with inheritance!) /// + +class Base1 { + x: number + public implicit(): number { return this.x; } + explicit(this: Base1): number { return this.x; } + static implicitStatic(): number { return this.x; } + static explicitStatic(this: typeof Base1): number { return this.x; } +} +class Derived1 extends Base1 { + y: number +} +class Base2 { + y: number + implicit(): number { return this.y; } + explicit(this: Base1): number { return this.x; } +} +class Derived2 extends Base2 { + x: number +} + + +let b1 = new Base1(); +let d1 = new Derived1(); +let b2 = new Base2(); +let d2 = new Derived2(); + +b1.implicit = b2.implicit // error, 'this.y' not in C: { x } (c assignable to e) +b1.explicit = b2.implicit // error, 'y' not in C: { x } (c assignable to e) + +d1.explicit = b2.implicit // error, 'y' not in C: { x } (c assignable to e) + +////// use this-type for construction with new //// +function VoidThis(this: void) { + +} +function ImplicitVoidThis() { + +} +let voidThis = new VoidThis(); +let implicitVoidThis = new ImplicitVoidThis(); + + +///// parse errors ///// +function notFirst(a: number, this: C): number { return this.n; } +function modifiers(async this: C): number { return this.n; } +function restParam(...this: C): number { return this.n; } +function optional(this?: C): number { return this.n; } +function decorated(@deco() this: C): number { return this.n; } +function initializer(this: C = new C()): number { return this.n; } + +// can't name parameters 'this' in a lambda. +c.explicitProperty = (this, m) => m + this.n; diff --git a/tests/cases/fourslash/memberListOnExplicitThis.ts b/tests/cases/fourslash/memberListOnExplicitThis.ts new file mode 100644 index 00000000000..cf57717183c --- /dev/null +++ b/tests/cases/fourslash/memberListOnExplicitThis.ts @@ -0,0 +1,30 @@ +// @strictThis: true +/// + +////interface Restricted { +//// n: number; +////} +////class C1 implements Restricted { +//// n: number; +//// m: number; +//// f() {this./*1*/} // test on 'this.' +//// g(this: Restricted) {this./*2*/} +////} +////function f() {this./*3*/} +////function g(this: Restricted) {this./*4*/} + +goTo.marker('1'); +verify.memberListContains('f', '(method) C1.f(this: this): void'); +verify.memberListContains('g', '(method) C1.g(this: Restricted): void'); +verify.memberListContains('n', '(property) C1.n: number'); +verify.memberListContains('m', '(property) C1.m: number'); + +goTo.marker('2'); +verify.memberListContains('n', '(property) Restricted.n: number'); + +goTo.marker('3'); +verify.memberListIsEmpty(); + +goTo.marker('4'); +verify.memberListContains('n', '(property) Restricted.n: number'); + From a4f1154377bc62320ddb73d2ac448f3bc0089768 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 29 Jan 2016 14:51:35 -0800 Subject: [PATCH 030/274] Fix free function bug in cachingInServerLSHost --- tests/cases/unittests/cachingInServerLSHost.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/cases/unittests/cachingInServerLSHost.ts b/tests/cases/unittests/cachingInServerLSHost.ts index 59f97f434e6..6d7b3fdbc28 100644 --- a/tests/cases/unittests/cachingInServerLSHost.ts +++ b/tests/cases/unittests/cachingInServerLSHost.ts @@ -123,7 +123,7 @@ module ts { } fileExistsIsCalled = true; assert.isTrue(fileName.indexOf('/f2.') !== -1); - return originalFileExists(fileName); + return originalFileExists.call(serverHost, fileName); }; let newContent = `import {x} from "f2"`; rootScriptInfo.editContent(0, rootScriptInfo.content.length, newContent); @@ -147,7 +147,7 @@ module ts { } fileExistsCalled = true; assert.isTrue(fileName.indexOf('/f1.') !== -1); - return originalFileExists(fileName); + return originalFileExists.call(serverHost, fileName); }; let newContent = `import {x} from "f1"`; @@ -192,7 +192,7 @@ module ts { fileExistsCalledForBar = fileName.indexOf("/bar.") !== -1; } - return originalFileExists(fileName); + return originalFileExists.call(serverHost, fileName); }; let { project, rootScriptInfo } = createProject(root.name, serverHost); From d030889166b56fe3e4a2fb080711807245422c98 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 29 Jan 2016 14:52:47 -0800 Subject: [PATCH 031/274] Update baselines 1. Display of `this` changes for quick info. 2. The type of Function.call/apply/bind is more precise. --- .../assignmentToObjectAndFunction.errors.txt | 4 +- ...ArrowFunctionCapturesArguments_es6.symbols | 4 +- ...ncArrowFunctionCapturesArguments_es6.types | 12 +-- ...nctionsInFunctionParameterDefaults.symbols | 4 +- ...functionsInFunctionParameterDefaults.types | 4 +- .../baselines/reference/functionType.symbols | 4 +- tests/baselines/reference/functionType.types | 6 +- .../genericTypeParameterEquivalence2.symbols | 4 +- .../genericTypeParameterEquivalence2.types | 6 +- ...llSignatureAppearsToBeFunctionType.symbols | 8 +- ...CallSignatureAppearsToBeFunctionType.types | 8 +- .../returnTypeParameterWithModules.symbols | 4 +- .../returnTypeParameterWithModules.types | 4 +- tests/cases/fourslash/commentsClassMembers.ts | 2 +- .../fourslash/instanceTypesForGenericType1.ts | 2 +- tests/cases/fourslash/quickInfoOnThis.ts | 77 +++++++++++++++++-- tests/cases/fourslash/thisBindingInLambda.ts | 2 +- 17 files changed, 108 insertions(+), 47 deletions(-) diff --git a/tests/baselines/reference/assignmentToObjectAndFunction.errors.txt b/tests/baselines/reference/assignmentToObjectAndFunction.errors.txt index 2e85ee101f5..454ac41b5b8 100644 --- a/tests/baselines/reference/assignmentToObjectAndFunction.errors.txt +++ b/tests/baselines/reference/assignmentToObjectAndFunction.errors.txt @@ -5,7 +5,7 @@ tests/cases/compiler/assignmentToObjectAndFunction.ts(8,5): error TS2322: Type ' Property 'apply' is missing in type '{}'. tests/cases/compiler/assignmentToObjectAndFunction.ts(29,5): error TS2322: Type 'typeof bad' is not assignable to type 'Function'. Types of property 'apply' are incompatible. - Type 'number' is not assignable to type '(thisArg: any, argArray?: any) => any'. + Type 'number' is not assignable to type '{ (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; }'. ==== tests/cases/compiler/assignmentToObjectAndFunction.ts (3 errors) ==== @@ -48,4 +48,4 @@ tests/cases/compiler/assignmentToObjectAndFunction.ts(29,5): error TS2322: Type ~~~~~~~~~~ !!! error TS2322: Type 'typeof bad' is not assignable to type 'Function'. !!! error TS2322: Types of property 'apply' are incompatible. -!!! error TS2322: Type 'number' is not assignable to type '(thisArg: any, argArray?: any) => any'. \ No newline at end of file +!!! error TS2322: Type 'number' is not assignable to type '{ (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; }'. \ No newline at end of file diff --git a/tests/baselines/reference/asyncArrowFunctionCapturesArguments_es6.symbols b/tests/baselines/reference/asyncArrowFunctionCapturesArguments_es6.symbols index 2f516d7d758..bc061211b88 100644 --- a/tests/baselines/reference/asyncArrowFunctionCapturesArguments_es6.symbols +++ b/tests/baselines/reference/asyncArrowFunctionCapturesArguments_es6.symbols @@ -10,9 +10,9 @@ class C { var fn = async () => await other.apply(this, arguments); >fn : Symbol(fn, Decl(asyncArrowFunctionCapturesArguments_es6.ts, 3, 9)) ->other.apply : Symbol(Function.apply, Decl(lib.d.ts, --, --)) +>other.apply : Symbol(Function.apply, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >other : Symbol(other, Decl(asyncArrowFunctionCapturesArguments_es6.ts, 1, 13)) ->apply : Symbol(Function.apply, Decl(lib.d.ts, --, --)) +>apply : Symbol(Function.apply, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >this : Symbol(C, Decl(asyncArrowFunctionCapturesArguments_es6.ts, 0, 0)) >arguments : Symbol(arguments) } diff --git a/tests/baselines/reference/asyncArrowFunctionCapturesArguments_es6.types b/tests/baselines/reference/asyncArrowFunctionCapturesArguments_es6.types index 76853858c5c..18a08ffface 100644 --- a/tests/baselines/reference/asyncArrowFunctionCapturesArguments_es6.types +++ b/tests/baselines/reference/asyncArrowFunctionCapturesArguments_es6.types @@ -9,13 +9,13 @@ class C { >other : () => void var fn = async () => await other.apply(this, arguments); ->fn : () => Promise ->async () => await other.apply(this, arguments) : () => Promise ->await other.apply(this, arguments) : any ->other.apply(this, arguments) : any ->other.apply : (thisArg: any, argArray?: any) => any +>fn : () => Promise +>async () => await other.apply(this, arguments) : () => Promise +>await other.apply(this, arguments) : void +>other.apply(this, arguments) : void +>other.apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } >other : () => void ->apply : (thisArg: any, argArray?: any) => any +>apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } >this : this >arguments : IArguments } diff --git a/tests/baselines/reference/fatarrowfunctionsInFunctionParameterDefaults.symbols b/tests/baselines/reference/fatarrowfunctionsInFunctionParameterDefaults.symbols index ea0ed9a605c..b836bc88573 100644 --- a/tests/baselines/reference/fatarrowfunctionsInFunctionParameterDefaults.symbols +++ b/tests/baselines/reference/fatarrowfunctionsInFunctionParameterDefaults.symbols @@ -12,7 +12,7 @@ function fn(x = () => this, y = x()) { } fn.call(4); // Should be 4 ->fn.call : Symbol(Function.call, Decl(lib.d.ts, --, --)) +>fn.call : Symbol(Function.call, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >fn : Symbol(fn, Decl(fatarrowfunctionsInFunctionParameterDefaults.ts, 0, 0)) ->call : Symbol(Function.call, Decl(lib.d.ts, --, --)) +>call : Symbol(Function.call, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) diff --git a/tests/baselines/reference/fatarrowfunctionsInFunctionParameterDefaults.types b/tests/baselines/reference/fatarrowfunctionsInFunctionParameterDefaults.types index 55d72e854d3..58c576bf24e 100644 --- a/tests/baselines/reference/fatarrowfunctionsInFunctionParameterDefaults.types +++ b/tests/baselines/reference/fatarrowfunctionsInFunctionParameterDefaults.types @@ -16,8 +16,8 @@ function fn(x = () => this, y = x()) { fn.call(4); // Should be 4 >fn.call(4) : any ->fn.call : (thisArg: any, ...argArray: any[]) => any +>fn.call : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, ...argArray: any[]): U; (this: Function, thisArg: any, ...argArray: any[]): any; } >fn : (x?: () => any, y?: any) => any ->call : (thisArg: any, ...argArray: any[]) => any +>call : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, ...argArray: any[]): U; (this: Function, thisArg: any, ...argArray: any[]): any; } >4 : number diff --git a/tests/baselines/reference/functionType.symbols b/tests/baselines/reference/functionType.symbols index 30a5a7cc447..65347d39b5a 100644 --- a/tests/baselines/reference/functionType.symbols +++ b/tests/baselines/reference/functionType.symbols @@ -3,9 +3,9 @@ function salt() {} >salt : Symbol(salt, Decl(functionType.ts, 0, 0)) salt.apply("hello", []); ->salt.apply : Symbol(Function.apply, Decl(lib.d.ts, --, --)) +>salt.apply : Symbol(Function.apply, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >salt : Symbol(salt, Decl(functionType.ts, 0, 0)) ->apply : Symbol(Function.apply, Decl(lib.d.ts, --, --)) +>apply : Symbol(Function.apply, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) (new Function("return 5"))(); >Function : Symbol(Function, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) diff --git a/tests/baselines/reference/functionType.types b/tests/baselines/reference/functionType.types index e7ea7a47edf..9183ec4a13e 100644 --- a/tests/baselines/reference/functionType.types +++ b/tests/baselines/reference/functionType.types @@ -3,10 +3,10 @@ function salt() {} >salt : () => void salt.apply("hello", []); ->salt.apply("hello", []) : any ->salt.apply : (thisArg: any, argArray?: any) => any +>salt.apply("hello", []) : void +>salt.apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } >salt : () => void ->apply : (thisArg: any, argArray?: any) => any +>apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } >"hello" : string >[] : undefined[] diff --git a/tests/baselines/reference/genericTypeParameterEquivalence2.symbols b/tests/baselines/reference/genericTypeParameterEquivalence2.symbols index cd558fdd10a..1aa22b1e994 100644 --- a/tests/baselines/reference/genericTypeParameterEquivalence2.symbols +++ b/tests/baselines/reference/genericTypeParameterEquivalence2.symbols @@ -24,9 +24,9 @@ function compose(f: (b: B) => C, g: (a:A) => B): (a:A) => C { return f(g.apply(null, a)); >f : Symbol(f, Decl(genericTypeParameterEquivalence2.ts, 1, 26)) ->g.apply : Symbol(Function.apply, Decl(lib.d.ts, --, --)) +>g.apply : Symbol(Function.apply, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >g : Symbol(g, Decl(genericTypeParameterEquivalence2.ts, 1, 41)) ->apply : Symbol(Function.apply, Decl(lib.d.ts, --, --)) +>apply : Symbol(Function.apply, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >a : Symbol(a, Decl(genericTypeParameterEquivalence2.ts, 2, 21)) }; diff --git a/tests/baselines/reference/genericTypeParameterEquivalence2.types b/tests/baselines/reference/genericTypeParameterEquivalence2.types index 3b2c533543d..9fdb03b0fbe 100644 --- a/tests/baselines/reference/genericTypeParameterEquivalence2.types +++ b/tests/baselines/reference/genericTypeParameterEquivalence2.types @@ -26,10 +26,10 @@ function compose(f: (b: B) => C, g: (a:A) => B): (a:A) => C { return f(g.apply(null, a)); >f(g.apply(null, a)) : C >f : (b: B) => C ->g.apply(null, a) : any ->g.apply : (thisArg: any, argArray?: any) => any +>g.apply(null, a) : B +>g.apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } >g : (a: A) => B ->apply : (thisArg: any, argArray?: any) => any +>apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } >null : null >a : A diff --git a/tests/baselines/reference/objectTypeWithCallSignatureAppearsToBeFunctionType.symbols b/tests/baselines/reference/objectTypeWithCallSignatureAppearsToBeFunctionType.symbols index 60b7b08397a..08d3d75e9dc 100644 --- a/tests/baselines/reference/objectTypeWithCallSignatureAppearsToBeFunctionType.symbols +++ b/tests/baselines/reference/objectTypeWithCallSignatureAppearsToBeFunctionType.symbols @@ -20,9 +20,9 @@ var r2b: (x: any, y?: any) => any = i.apply; >r2b : Symbol(r2b, Decl(objectTypeWithCallSignatureAppearsToBeFunctionType.ts, 9, 3)) >x : Symbol(x, Decl(objectTypeWithCallSignatureAppearsToBeFunctionType.ts, 9, 10)) >y : Symbol(y, Decl(objectTypeWithCallSignatureAppearsToBeFunctionType.ts, 9, 17)) ->i.apply : Symbol(Function.apply, Decl(lib.d.ts, --, --)) +>i.apply : Symbol(Function.apply, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >i : Symbol(i, Decl(objectTypeWithCallSignatureAppearsToBeFunctionType.ts, 7, 3)) ->apply : Symbol(Function.apply, Decl(lib.d.ts, --, --)) +>apply : Symbol(Function.apply, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) var b: { >b : Symbol(b, Decl(objectTypeWithCallSignatureAppearsToBeFunctionType.ts, 11, 3)) @@ -38,7 +38,7 @@ var rb4: (x: any, y?: any) => any = b.apply; >rb4 : Symbol(rb4, Decl(objectTypeWithCallSignatureAppearsToBeFunctionType.ts, 16, 3)) >x : Symbol(x, Decl(objectTypeWithCallSignatureAppearsToBeFunctionType.ts, 16, 10)) >y : Symbol(y, Decl(objectTypeWithCallSignatureAppearsToBeFunctionType.ts, 16, 17)) ->b.apply : Symbol(Function.apply, Decl(lib.d.ts, --, --)) +>b.apply : Symbol(Function.apply, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >b : Symbol(b, Decl(objectTypeWithCallSignatureAppearsToBeFunctionType.ts, 11, 3)) ->apply : Symbol(Function.apply, Decl(lib.d.ts, --, --)) +>apply : Symbol(Function.apply, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) diff --git a/tests/baselines/reference/objectTypeWithCallSignatureAppearsToBeFunctionType.types b/tests/baselines/reference/objectTypeWithCallSignatureAppearsToBeFunctionType.types index 74d8ef57d67..496734c9183 100644 --- a/tests/baselines/reference/objectTypeWithCallSignatureAppearsToBeFunctionType.types +++ b/tests/baselines/reference/objectTypeWithCallSignatureAppearsToBeFunctionType.types @@ -21,9 +21,9 @@ var r2b: (x: any, y?: any) => any = i.apply; >r2b : (x: any, y?: any) => any >x : any >y : any ->i.apply : (thisArg: any, argArray?: any) => any +>i.apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } >i : I ->apply : (thisArg: any, argArray?: any) => any +>apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } var b: { >b : () => void @@ -40,7 +40,7 @@ var rb4: (x: any, y?: any) => any = b.apply; >rb4 : (x: any, y?: any) => any >x : any >y : any ->b.apply : (thisArg: any, argArray?: any) => any +>b.apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } >b : () => void ->apply : (thisArg: any, argArray?: any) => any +>apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } diff --git a/tests/baselines/reference/returnTypeParameterWithModules.symbols b/tests/baselines/reference/returnTypeParameterWithModules.symbols index 7f8fab382a3..e3b7c50948f 100644 --- a/tests/baselines/reference/returnTypeParameterWithModules.symbols +++ b/tests/baselines/reference/returnTypeParameterWithModules.symbols @@ -12,13 +12,13 @@ module M1 { >A : Symbol(A, Decl(returnTypeParameterWithModules.ts, 1, 27)) return Array.prototype.reduce.apply(ar, e ? [f, e] : [f]); ->Array.prototype.reduce.apply : Symbol(Function.apply, Decl(lib.d.ts, --, --)) +>Array.prototype.reduce.apply : Symbol(Function.apply, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >Array.prototype.reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >Array.prototype : Symbol(ArrayConstructor.prototype, Decl(lib.d.ts, --, --)) >Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >prototype : Symbol(ArrayConstructor.prototype, Decl(lib.d.ts, --, --)) >reduce : Symbol(Array.reduce, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) ->apply : Symbol(Function.apply, Decl(lib.d.ts, --, --)) +>apply : Symbol(Function.apply, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >ar : Symbol(ar, Decl(returnTypeParameterWithModules.ts, 1, 30)) >e : Symbol(e, Decl(returnTypeParameterWithModules.ts, 1, 36)) >f : Symbol(f, Decl(returnTypeParameterWithModules.ts, 1, 33)) diff --git a/tests/baselines/reference/returnTypeParameterWithModules.types b/tests/baselines/reference/returnTypeParameterWithModules.types index be09b8f46b0..ffb058daa08 100644 --- a/tests/baselines/reference/returnTypeParameterWithModules.types +++ b/tests/baselines/reference/returnTypeParameterWithModules.types @@ -13,13 +13,13 @@ module M1 { return Array.prototype.reduce.apply(ar, e ? [f, e] : [f]); >Array.prototype.reduce.apply(ar, e ? [f, e] : [f]) : any ->Array.prototype.reduce.apply : (thisArg: any, argArray?: any) => any +>Array.prototype.reduce.apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } >Array.prototype.reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue?: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } >Array.prototype : any[] >Array : ArrayConstructor >prototype : any[] >reduce : { (callbackfn: (previousValue: any, currentValue: any, currentIndex: number, array: any[]) => any, initialValue?: any): any; (callbackfn: (previousValue: U, currentValue: any, currentIndex: number, array: any[]) => U, initialValue: U): U; } ->apply : (thisArg: any, argArray?: any) => any +>apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } >ar : any >e ? [f, e] : [f] : any[] >e : any diff --git a/tests/cases/fourslash/commentsClassMembers.ts b/tests/cases/fourslash/commentsClassMembers.ts index 54b4f0253d4..d719253a57b 100644 --- a/tests/cases/fourslash/commentsClassMembers.ts +++ b/tests/cases/fourslash/commentsClassMembers.ts @@ -694,7 +694,7 @@ verify.completionListContains("a", "(parameter) a: number", "this is first param verify.quickInfoIs("(parameter) a: number", "this is first parameter a\nmore info about a"); goTo.marker('116'); -verify.quickInfoIs("class cWithConstructorProperty", ""); +verify.quickInfoIs("this: this", ""); goTo.marker('117'); verify.quickInfoIs("(local var) bbbb: number", ""); diff --git a/tests/cases/fourslash/instanceTypesForGenericType1.ts b/tests/cases/fourslash/instanceTypesForGenericType1.ts index 96ee175383e..a3d119785bf 100644 --- a/tests/cases/fourslash/instanceTypesForGenericType1.ts +++ b/tests/cases/fourslash/instanceTypesForGenericType1.ts @@ -11,4 +11,4 @@ goTo.marker('1'); verify.quickInfoIs('(property) G.self: G'); goTo.marker('2'); -verify.quickInfoIs('class G'); \ No newline at end of file +verify.quickInfoIs('this: this'); \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoOnThis.ts b/tests/cases/fourslash/quickInfoOnThis.ts index c4eecfca5d5..cef78efe0cc 100644 --- a/tests/cases/fourslash/quickInfoOnThis.ts +++ b/tests/cases/fourslash/quickInfoOnThis.ts @@ -1,15 +1,76 @@ +// @strictThis: true /// - -////function someFn1(someFn: { (): void; }) { } +////interface Restricted { +//// n: number; +////} +////function wrapper(wrapped: { (): void; }) { } ////class Foo { -//// public bar() { -//// someFn1( -//// function doSomething() { -//// console.log(th/**/is); +//// n: number; +//// public implicitThis() { +//// wrapper( +//// function implicitVoid() { +//// console.log(th/*1*/is); //// } //// ) +//// console.log(th/*2*/is); +//// } +//// public explicitInterface(th/*3*/is: Restricted) { +//// console.log(th/*4*/is); +//// } +//// public explicitClass(th/*5*/is: Foo) { +//// console.log(th/*6*/is); //// } ////} +////class Bar { +//// public implicitThis() { +//// console.log(th/*7*/is); +//// } +//// public explicitThis(this: Bar) { +//// console.log(thi/*8*/s); +//// } +////} +//// +////function implicitVoid(x: number): void { +//// return th/*9*/is; +////} +////function explicitVoid(th/*10*/is: void, x: number): void { +//// return th/*11*/is; +////} +////function explicitInterface(th/*12*/is: Restricted): void { +//// console.log(thi/*13*/s); +////} +////function explicitLiteral(th/*14*/is: { n: number }): void { +//// console.log(th/*15*/is); +////} -goTo.marker(); -verify.quickInfoIs('any'); +goTo.marker('1'); +verify.quickInfoIs('void'); +goTo.marker('2'); +verify.quickInfoIs('this: this'); +goTo.marker('3'); +verify.quickInfoIs('(parameter) this: Restricted'); +goTo.marker('4'); +verify.quickInfoIs('this: Restricted'); +goTo.marker('5'); +verify.quickInfoIs('(parameter) this: Foo'); +goTo.marker('6'); +verify.quickInfoIs('this: Foo'); +goTo.marker('7'); +verify.quickInfoIs('this: this'); +goTo.marker('8'); +verify.quickInfoIs('this: Bar'); +goTo.marker('9'); +verify.quickInfoIs('void'); +goTo.marker('10'); +verify.quickInfoIs('(parameter) this: void'); +goTo.marker('11'); +verify.quickInfoIs('void'); +goTo.marker('12'); +verify.quickInfoIs('(parameter) this: Restricted'); +goTo.marker('13'); +verify.quickInfoIs('this: Restricted'); +goTo.marker('14'); + +verify.quickInfoIs('(parameter) this: {\n n: number;\n}'); +goTo.marker('15'); +verify.quickInfoIs('this: {\n n: number;\n}'); \ No newline at end of file diff --git a/tests/cases/fourslash/thisBindingInLambda.ts b/tests/cases/fourslash/thisBindingInLambda.ts index f6dfdbdec08..d9c43796bd8 100644 --- a/tests/cases/fourslash/thisBindingInLambda.ts +++ b/tests/cases/fourslash/thisBindingInLambda.ts @@ -9,4 +9,4 @@ ////} goTo.marker(); -verify.quickInfoIs('class Greeter'); +verify.quickInfoIs('this: this'); From 675e0816d40cbe1fcd269dc98fff5e8e19bbb9cd Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 2 Feb 2016 14:46:44 -0800 Subject: [PATCH 032/274] Make this-type of bind's return explicit --- src/lib/core.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/core.d.ts b/src/lib/core.d.ts index fe2fd6b79f6..5a94b21b0fb 100644 --- a/src/lib/core.d.ts +++ b/src/lib/core.d.ts @@ -232,7 +232,7 @@ interface Function { * @param thisArg An object to which the this keyword can refer inside the new function. * @param argArray A list of arguments to be passed to the new function. */ - bind(this: (this: T, ...argArray: any[]) => U, thisArg: T, ...argArray: any[]): (...argArray: any[]) => U; + bind(this: (this: T, ...argArray: any[]) => U, thisArg: T, ...argArray: any[]): (this: void, ...argArray: any[]) => U; bind(this: Function, thisArg: any, ...argArray: any[]): any; prototype: any; From f6361cec665339077ee9df83f0fd887834c5c5a7 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 2 Feb 2016 16:00:52 -0800 Subject: [PATCH 033/274] Undo strictThis-clean changes Also fix other lint. --- src/compiler/checker.ts | 2 +- src/compiler/core.ts | 19 ++++++----- src/compiler/program.ts | 3 +- src/compiler/sourcemap.ts | 8 ++--- src/compiler/sys.ts | 2 +- src/compiler/types.ts | 16 +++++----- src/compiler/utilities.ts | 20 ++++++------ src/harness/harness.ts | 30 ++++++++--------- src/harness/loggedIO.ts | 32 +++++++++---------- src/server/editorServices.ts | 2 +- src/server/node.d.ts | 4 +-- .../formatting/ruleOperationContext.ts | 4 +-- src/services/services.ts | 6 ++-- src/services/utilities.ts | 2 +- 14 files changed, 73 insertions(+), 77 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3940be5d698..bfa398f190d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4115,7 +4115,7 @@ namespace ts { else { parameters.push(paramSymbol); } - + if (param.type && param.type.kind === SyntaxKind.StringLiteralType) { hasStringLiterals = true; } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index ab8de44ec98..21536da36ff 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -818,26 +818,25 @@ namespace ts { getSignatureConstructor(): new (checker: TypeChecker) => Signature; } - // TODO: Add a 'this' parameter after I update the previous-version compiler function Symbol(flags: SymbolFlags, name: string) { - (this).flags = flags; - (this).name = name; - (this).declarations = undefined; + this.flags = flags; + this.name = name; + this.declarations = undefined; } function Type(checker: TypeChecker, flags: TypeFlags) { - (this).flags = flags; + this.flags = flags; } function Signature(checker: TypeChecker) { } function Node(kind: SyntaxKind, pos: number, end: number) { - (this).kind = kind; - (this).pos = pos; - (this).end = end; - (this).flags = NodeFlags.None; - (this).parent = undefined; + this.kind = kind; + this.pos = pos; + this.end = end; + this.flags = NodeFlags.None; + this.parent = undefined; } export let objectAllocator: ObjectAllocator = { diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 88c77aa5759..803ae47b0fd 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -933,9 +933,8 @@ namespace ts { return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = createTypeChecker(program, /*produceDiagnostics:*/ false)); } - // TODO: needs to have this: Program function emit(sourceFile?: SourceFile, writeFileCallback?: WriteFileCallback, cancellationToken?: CancellationToken): EmitResult { - return runWithCancellationToken(() => emitWorker((this), sourceFile, writeFileCallback, cancellationToken)); + return runWithCancellationToken(() => emitWorker(this, sourceFile, writeFileCallback, cancellationToken)); } function isEmitBlocked(emitFileName: string): boolean { diff --git a/src/compiler/sourcemap.ts b/src/compiler/sourcemap.ts index fb61f8b78b8..8abf1432b0c 100644 --- a/src/compiler/sourcemap.ts +++ b/src/compiler/sourcemap.ts @@ -4,10 +4,10 @@ namespace ts { export interface SourceMapWriter { getSourceMapData(): SourceMapData; - setSourceFile: (sourceFile: SourceFile) => void; - emitPos: (pos: number) => void; - emitStart: (range: TextRange) => void; - emitEnd: (range: TextRange, stopOverridingSpan?: boolean) => void; + setSourceFile(sourceFile: SourceFile): void; + emitPos(pos: number): void; + emitStart(range: TextRange): void; + emitEnd(range: TextRange, stopOverridingSpan?: boolean): void; changeEmitSourcePos(): void; getText(): string; getSourceMappingURL(): string; diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 1a9da39bf9a..bf25d39aa43 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -63,7 +63,7 @@ namespace ts { useCaseSensitiveFileNames?: boolean; echo(s: string): void; quit(exitCode?: number): void; - fileExists: (path: string) => boolean; + fileExists(path: string): boolean; directoryExists(path: string): boolean; createDirectory(path: string): void; resolvePath(path: string): string; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 9c2612d96b6..6e0ccc3bf66 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1593,8 +1593,8 @@ namespace ts { } export interface ScriptReferenceHost { - getCompilerOptions: () => CompilerOptions; - getSourceFile: (fileName: string) => SourceFile; + getCompilerOptions(): CompilerOptions; + getSourceFile(fileName: string): SourceFile; getCurrentDirectory(): string; } @@ -1625,7 +1625,7 @@ namespace ts { /** * Get a list of files in the program */ - getSourceFiles: () => SourceFile[]; + getSourceFiles(): SourceFile[]; /** * Emits the JavaScript and declaration files. If targetSourceFile is not specified, then @@ -1650,7 +1650,7 @@ namespace ts { */ getTypeChecker(): TypeChecker; - /* @internal */ getCommonSourceDirectory: () => string; + /* @internal */ getCommonSourceDirectory(): string; // For testing purposes only. Should not be used by any other consumers (including the // language service). @@ -1905,11 +1905,11 @@ namespace ts { getReferencedImportDeclaration(node: Identifier): Declaration; getReferencedDeclarationWithCollidingName(node: Identifier): Declaration; isDeclarationWithCollidingName(node: Declaration): boolean; - isValueAliasDeclaration: (node: Node) => boolean; - isReferencedAliasDeclaration: (node: Node, checkChildren?: boolean) => boolean; + isValueAliasDeclaration(node: Node): boolean; + isReferencedAliasDeclaration(node: Node, checkChildren?: boolean): boolean; isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean; getNodeCheckFlags(node: Node): NodeCheckFlags; - isDeclarationVisible: (node: Declaration) => boolean; + isDeclarationVisible(node: Declaration): boolean; collectLinkedAliases(node: Identifier): Node[]; isImplementationOfOverload(node: FunctionLikeDeclaration): boolean; writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; @@ -2430,7 +2430,7 @@ namespace ts { rootDir?: string; sourceMap?: boolean; sourceRoot?: string; - strictThis?: boolean, + strictThis?: boolean; suppressExcessPropertyErrors?: boolean; suppressImplicitAnyIndexErrors?: boolean; target?: ScriptTarget; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index bce821c3756..bab66eb0688 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -32,11 +32,11 @@ namespace ts { } export interface EmitHost extends ScriptReferenceHost { - getSourceFiles: () => SourceFile[]; + getSourceFiles(): SourceFile[]; - getCommonSourceDirectory: () => string; - getCanonicalFileName: (fileName: string) => string; - getNewLine: () => string; + getCommonSourceDirectory(): string; + getCanonicalFileName(fileName: string): string; + getNewLine(): string; isEmitBlocked(emitFileName: string): boolean; @@ -1869,11 +1869,11 @@ namespace ts { } export interface EmitTextWriter { - write: (s: string) => void; - writeTextOfNode: (text: string, node: Node) => void; - writeLine: () => void; - increaseIndent: () => void; - decreaseIndent: () => void; + write(s: string): void; + writeTextOfNode(text: string, node: Node): void; + writeLine(): void; + increaseIndent(): void; + decreaseIndent(): void; getText(): string; rawWrite(s: string): void; writeLiteral(s: string): void; @@ -2490,7 +2490,7 @@ namespace ts { * as the fallback implementation does not check for circular references by default. */ export const stringify: (value: any) => string = typeof JSON !== "undefined" && JSON.stringify - ? JSON.stringify + ? JSON.stringify : stringifyFallback; /** diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 3b211a0d91a..2b0c95c0a61 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -417,24 +417,24 @@ namespace Harness.Path { namespace Harness { export interface IO { - args(): string[]; newLine(): string; - readFile(this: ts.System | IO, path: string): string; - writeFile(path: string, contents: string): void; - resolvePath(path: string): string; - fileExists: (fileName: string) => boolean; - directoryExists: (path: string) => boolean; - createDirectory(path: string): void; - getExecutingFilePath(this: ts.System | IO): string; getCurrentDirectory(): string; - readDirectory(path: string, extension?: string, exclude?: string[]): string[]; - getMemoryUsage?(): number; - exit(exitCode?: number): void; - deleteFile(fileName: string): void; - directoryName: (path: string) => string; - listFiles(path: string, filter: RegExp, options?: { recursive?: boolean }): string[]; - log: (text: string) => void; useCaseSensitiveFileNames(): boolean; + resolvePath(path: string): string; + readFile(path: string): string; + writeFile(path: string, contents: string): void; + directoryName(path: string): string; + createDirectory(path: string): void; + fileExists(fileName: string): boolean; + directoryExists(path: string): boolean; + deleteFile(fileName: string): void; + listFiles(path: string, filter: RegExp, options?: { recursive?: boolean }): string[]; + log(text: string): void; + getMemoryUsage?(): number; + args(): string[]; + getExecutingFilePath(): string; + exit(exitCode?: number): void; + readDirectory(path: string, extension?: string, exclude?: string[]): string[]; } export var IO: IO; diff --git a/src/harness/loggedIO.ts b/src/harness/loggedIO.ts index dbc05112f3e..cc5e06ab920 100644 --- a/src/harness/loggedIO.ts +++ b/src/harness/loggedIO.ts @@ -70,11 +70,11 @@ interface IOLog { interface PlaybackControl { startReplayFromFile(logFileName: string): void; - startReplayFromString(this: PlaybackControl, logContents: string): void; - startReplayFromData(this: PlaybackControl, log: IOLog): void; + startReplayFromString(logContents: string): void; + startReplayFromData(log: IOLog): void; endReplay(): void; startRecord(logFileName: string): void; - endRecord(this: PlaybackControl): void; + endRecord(): void; } namespace Playback { @@ -127,8 +127,6 @@ namespace Playback { function initWrapper(wrapper: PlaybackSystem, underlying: ts.System): void; function initWrapper(wrapper: PlaybackIO, underlying: Harness.IO): void; function initWrapper(wrapper: PlaybackSystem | PlaybackIO, underlying: ts.System | Harness.IO): void { - // TODO: Define a common interface over ts.System | Harness.IO and stop passing a union type. - const underlyingShim: any = underlying; ts.forEach(Object.keys(underlying), prop => { (wrapper)[prop] = (underlying)[prop]; }); @@ -156,20 +154,20 @@ namespace Playback { }; wrapper.startReplayFromFile = logFn => { - wrapper.startReplayFromString(underlyingShim.readFile(logFn)); + wrapper.startReplayFromString(underlying.readFile(logFn)); }; wrapper.endRecord = () => { if (recordLog !== undefined) { let i = 0; const fn = () => recordLogFileNameBase + i + ".json"; - while (underlyingShim.fileExists(fn())) i++; - underlyingShim.writeFile(fn(), JSON.stringify(recordLog)); + while (underlying.fileExists(fn())) i++; + underlying.writeFile(fn(), JSON.stringify(recordLog)); recordLog = undefined; } }; wrapper.fileExists = recordReplay(wrapper.fileExists, underlying)( - path => callAndRecord(underlyingShim.fileExists(path), recordLog.fileExists, { path }), + path => callAndRecord(underlying.fileExists(path), recordLog.fileExists, { path }), memoize(path => { // If we read from the file, it must exist if (findResultByPath(wrapper, replayLog.filesRead, path, null) !== null) { @@ -186,10 +184,10 @@ namespace Playback { return replayLog.executingPath; } else if (recordLog !== undefined) { - return recordLog.executingPath = underlyingShim.getExecutingFilePath(); + return recordLog.executingPath = underlying.getExecutingFilePath(); } else { - return underlyingShim.getExecutingFilePath(); + return underlying.getExecutingFilePath(); } }; @@ -198,20 +196,20 @@ namespace Playback { return replayLog.currentDirectory || ""; } else if (recordLog !== undefined) { - return recordLog.currentDirectory = underlyingShim.getCurrentDirectory(); + return recordLog.currentDirectory = underlying.getCurrentDirectory(); } else { - return underlyingShim.getCurrentDirectory(); + return underlying.getCurrentDirectory(); } }; wrapper.resolvePath = recordReplay(wrapper.resolvePath, underlying)( - path => callAndRecord(underlyingShim.resolvePath(path), recordLog.pathsResolved, { path }), + path => callAndRecord(underlying.resolvePath(path), recordLog.pathsResolved, { path }), memoize(path => findResultByFields(replayLog.pathsResolved, { path }, !ts.isRootedDiskPath(ts.normalizeSlashes(path)) && replayLog.currentDirectory ? replayLog.currentDirectory + "/" + path : ts.normalizeSlashes(path)))); wrapper.readFile = recordReplay(wrapper.readFile, underlying)( path => { - const result = underlyingShim.readFile(path); + const result = underlying.readFile(path); const logEntry = { path, codepage: 0, result: { contents: result, codepage: 0 } }; recordLog.filesRead.push(logEntry); return result; @@ -228,14 +226,14 @@ namespace Playback { (path, extension, exclude) => findResultByPath(wrapper, replayLog.directoriesRead.filter(d => d.extension === extension && ts.arrayIsEqualTo(d.exclude, exclude)), path)); wrapper.writeFile = recordReplay(wrapper.writeFile, underlying)( - (path: string, contents: string) => callAndRecord(underlyingShim.writeFile(path, contents), recordLog.filesWritten, { path, contents, bom: false }), + (path: string, contents: string) => callAndRecord(underlying.writeFile(path, contents), recordLog.filesWritten, { path, contents, bom: false }), (path: string, contents: string) => noOpReplay("writeFile")); wrapper.exit = (exitCode) => { if (recordLog !== undefined) { wrapper.endRecord(); } - underlyingShim.exit(exitCode); + underlying.exit(exitCode); }; } diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 5516b18e0de..e2ec5cc159f 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1834,7 +1834,7 @@ namespace ts.server { if (!rangeEnd) { rangeEnd = this.root.charCount(); } - const walkFns: ILineIndexWalker = { + const walkFns = { goSubtree: true, done: false, leaf: function (relativeStart: number, relativeLength: number, ll: LineLeaf) { diff --git a/src/server/node.d.ts b/src/server/node.d.ts index 8e4d8c28e9b..0bde0bb6602 100644 --- a/src/server/node.d.ts +++ b/src/server/node.d.ts @@ -68,7 +68,7 @@ interface BufferConstructor { new (array: any[]): Buffer; prototype: Buffer; isBuffer(obj: any): boolean; - byteLength: (string: string, encoding?: string) => number; + byteLength(string: string, encoding?: string): number; concat(list: Buffer[], totalLength?: number): Buffer; } declare var Buffer: BufferConstructor; @@ -190,7 +190,7 @@ declare namespace NodeJS { nextTick(callback: Function): void; umask(mask?: number): number; uptime(): number; - hrtime: (time?: number[]) => number[]; + hrtime(time?: number[]): number[]; // Worker send? (message: any, sendHandle?: any): void; diff --git a/src/services/formatting/ruleOperationContext.ts b/src/services/formatting/ruleOperationContext.ts index 3108095e8e6..47330faa0dd 100644 --- a/src/services/formatting/ruleOperationContext.ts +++ b/src/services/formatting/ruleOperationContext.ts @@ -6,8 +6,8 @@ namespace ts.formatting { export class RuleOperationContext { private customContextChecks: { (context: FormattingContext): boolean; }[]; - constructor(...funcs: { (this: typeof Rules, context: FormattingContext): boolean; }[]) { - this.customContextChecks = <{ (this: any, context: FormattingContext): boolean }[]>funcs; + constructor(...funcs: { (context: FormattingContext): boolean; }[]) { + this.customContextChecks = funcs; } static Any: RuleOperationContext = new RuleOperationContext(); diff --git a/src/services/services.ts b/src/services/services.ts index 1a43f9a744b..496dd7172ea 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -19,15 +19,15 @@ namespace ts { getChildCount(sourceFile?: SourceFile): number; getChildAt(index: number, sourceFile?: SourceFile): Node; getChildren(sourceFile?: SourceFile): Node[]; - getStart(this: Node, sourceFile?: SourceFile): number; + getStart(sourceFile?: SourceFile): number; getFullStart(): number; - getEnd(this: Node): number; + getEnd(): number; getWidth(sourceFile?: SourceFile): number; getFullWidth(): number; getLeadingTriviaWidth(sourceFile?: SourceFile): number; getFullText(sourceFile?: SourceFile): string; getText(sourceFile?: SourceFile): string; - getFirstToken(this: Node, sourceFile?: SourceFile): Node; + getFirstToken(sourceFile?: SourceFile): Node; getLastToken(sourceFile?: SourceFile): Node; } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 0363e45a64a..afdc85fffd8 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -769,7 +769,7 @@ namespace ts { * The default is CRLF. */ export function getNewLineOrDefaultFromHost(host: LanguageServiceHost | LanguageServiceShimHost) { - return (host).getNewLine ? (host).getNewLine() : carriageReturnLineFeed; + return host.getNewLine ? host.getNewLine() : carriageReturnLineFeed; } export function lineBreakPart() { From 0af56c0ee201209d997193160567a7547a766fd2 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 2 Feb 2016 16:27:01 -0800 Subject: [PATCH 034/274] Update error numbers in new tests after merge --- .../reference/thisTypeInFunctionsNegative.errors.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt index 49a4380977a..ce3b3eed6f8 100644 --- a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt @@ -91,8 +91,8 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(168,1): er tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(170,1): error TS2322: Type '(this: Base2) => number' is not assignable to type '(this: Base1) => number'. Types of parameters 'this' and 'this' are incompatible. Type 'Base1' is not assignable to type 'Base2'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(179,16): error TS2671: A function that is called with the 'new' keyword cannot have a 'this' type that is void. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(180,24): error TS2671: A function that is called with the 'new' keyword cannot have a 'this' type that is void. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(179,16): error TS2672: A function that is called with the 'new' keyword cannot have a 'this' type that is void. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(180,24): error TS2672: A function that is called with the 'new' keyword cannot have a 'this' type that is void. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(184,30): error TS2332: 'this' cannot be referenced in current location. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(185,26): error TS1003: Identifier expected. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(185,30): error TS1005: ',' expected. @@ -442,10 +442,10 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,35): e } let voidThis = new VoidThis(); ~~~~~~~~~~~~~~ -!!! error TS2671: A function that is called with the 'new' keyword cannot have a 'this' type that is void. +!!! error TS2672: A function that is called with the 'new' keyword cannot have a 'this' type that is void. let implicitVoidThis = new ImplicitVoidThis(); ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2671: A function that is called with the 'new' keyword cannot have a 'this' type that is void. +!!! error TS2672: A function that is called with the 'new' keyword cannot have a 'this' type that is void. ///// parse errors ///// From 8c87da523bd927a5579f6286946339ccc6d52de5 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 4 Feb 2016 15:43:43 -0800 Subject: [PATCH 035/274] First round of review comments addressed. Only major thing is a bug fix in `isContextSensitiveFunctionLikeDeclaration`, and turning on context sensitivity to `this` even with `--strictThis` off. --- src/compiler/checker.ts | 66 ++++++++++--------- .../reference/contextualTyping24.errors.txt | 2 +- .../baselines/reference/contextualTyping24.js | 2 +- .../looseThisTypeInFunctions.errors.txt | 32 +++++++-- .../reference/looseThisTypeInFunctions.js | 31 ++++++++- .../reference/thisTypeInFunctions.js | 8 +-- .../reference/thisTypeInFunctions.symbols | 8 +-- .../reference/thisTypeInFunctions.types | 26 ++++---- .../thisTypeInFunctionsNegative.errors.txt | 6 +- tests/cases/compiler/contextualTyping24.ts | 2 +- .../thisType/looseThisTypeInFunctions.ts | 17 ++++- .../types/thisType/thisTypeInFuncTemp.ts | 27 ++++++++ .../types/thisType/thisTypeInFunctions.ts | 8 +-- 13 files changed, 162 insertions(+), 73 deletions(-) create mode 100644 tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9188cfff55d..2303aa539f6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -131,8 +131,8 @@ namespace ts { const noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); - const anySignature = createSignature(undefined, undefined, emptyArray, undefined, anyType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false); - const unknownSignature = createSignature(undefined, undefined, emptyArray, undefined, unknownType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false); + const anySignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false); + const unknownSignature = createSignature(undefined, undefined, undefined, emptyArray, unknownType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false); const enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true); @@ -3540,7 +3540,7 @@ namespace ts { resolveObjectTypeMembers(type, source, typeParameters, typeArguments); } - function createSignature(declaration: SignatureDeclaration, typeParameters: TypeParameter[], parameters: Symbol[], thisType: Type, + function createSignature(declaration: SignatureDeclaration, typeParameters: TypeParameter[], thisType: Type, parameters: Symbol[], resolvedReturnType: Type, minArgumentCount: number, hasRestParameter: boolean, hasStringLiterals: boolean): Signature { const sig = new Signature(checker); sig.declaration = declaration; @@ -3555,7 +3555,7 @@ namespace ts { } function cloneSignature(sig: Signature): Signature { - return createSignature(sig.declaration, sig.typeParameters, sig.parameters, sig.thisType, sig.resolvedReturnType, + return createSignature(sig.declaration, sig.typeParameters, sig.thisType, sig.parameters, sig.resolvedReturnType, sig.minArgumentCount, sig.hasRestParameter, sig.hasStringLiterals); } @@ -3567,7 +3567,7 @@ namespace ts { const baseConstructorType = getBaseConstructorTypeOfClass(classType); const baseSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct); if (baseSignatures.length === 0) { - return [createSignature(undefined, classType.localTypeParameters, emptyArray, undefined, classType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)]; + return [createSignature(undefined, classType.localTypeParameters, undefined, emptyArray, classType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)]; } const baseTypeNode = getBaseTypeNodeOfClass(classType); const typeArguments = map(baseTypeNode.typeArguments, getTypeFromTypeNode); @@ -4098,6 +4098,7 @@ namespace ts { let hasStringLiterals = false; let minArgumentCount = -1; let thisType: Type = undefined; + let hasThisParameter: boolean; const isJSConstructSignature = isJSDocConstructSignature(declaration); let returnType: Type = undefined; @@ -4113,11 +4114,9 @@ namespace ts { const resolvedSymbol = resolveName(param, paramSymbol.name, SymbolFlags.Value, undefined, undefined); paramSymbol = resolvedSymbol; } - if (paramSymbol.name === "this") { - thisType = param.type && getTypeOfSymbol(paramSymbol); - if (i !== 0 || declaration.kind === SyntaxKind.Constructor) { - error(param, Diagnostics.this_cannot_be_referenced_in_current_location); - } + if (i == 0 && paramSymbol.name === "this") { + hasThisParameter = true; + thisType = param.type ? getTypeFromTypeNode(param.type) : unknownType; } else { parameters.push(paramSymbol); @@ -4129,7 +4128,7 @@ namespace ts { if (param.initializer || param.questionToken || param.dotDotDotToken) { if (minArgumentCount < 0) { - minArgumentCount = i - (thisType ? 1 : 0); + minArgumentCount = i - (hasThisParameter ? 1 : 0); } } else { @@ -4139,19 +4138,19 @@ namespace ts { } if (minArgumentCount < 0) { - minArgumentCount = declaration.parameters.length - (thisType ? 1 : 0); + minArgumentCount = declaration.parameters.length - (hasThisParameter ? 1 : 0); } - if (!thisType && compilerOptions.strictThis) { - if (declaration.kind === SyntaxKind.FunctionDeclaration - || declaration.kind === SyntaxKind.CallSignature - || declaration.kind == SyntaxKind.FunctionExpression - || declaration.kind === SyntaxKind.FunctionType) { + if (!hasThisParameter && compilerOptions.strictThis) { + if (declaration.kind === SyntaxKind.FunctionDeclaration || + declaration.kind === SyntaxKind.CallSignature || + declaration.kind == SyntaxKind.FunctionExpression || + declaration.kind === SyntaxKind.FunctionType) { thisType = voidType; } else if ((declaration.kind === SyntaxKind.MethodDeclaration || declaration.kind === SyntaxKind.MethodSignature) && (isClassLike(declaration.parent) || declaration.parent.kind === SyntaxKind.InterfaceDeclaration)) { thisType = declaration.flags & NodeFlags.Static ? - getWidenedType(checkExpression((declaration.parent).name)) : + getTypeOfSymbol(getSymbolOfNode(declaration.parent)) : getThisType(declaration.name); Debug.assert(!!thisType, "couldn't find implicit this type"); } @@ -4187,7 +4186,7 @@ namespace ts { } } - links.resolvedSignature = createSignature(declaration, typeParameters, parameters, thisType, returnType, minArgumentCount, hasRestParameter(declaration), hasStringLiterals); + links.resolvedSignature = createSignature(declaration, typeParameters, thisType, parameters, returnType, minArgumentCount, hasRestParameter(declaration), hasStringLiterals); } return links.resolvedSignature; } @@ -5105,8 +5104,8 @@ namespace ts { } } const result = createSignature(signature.declaration, freshTypeParameters, + signature.thisType && instantiateType(signature.thisType, mapper), instantiateList(signature.parameters, mapper, instantiateSymbol), - signature.thisType ? instantiateType(signature.thisType, mapper) : undefined, instantiateType(signature.resolvedReturnType, mapper), signature.minArgumentCount, signature.hasRestParameter, signature.hasStringLiterals); result.target = signature; @@ -5220,14 +5219,12 @@ namespace ts { } function isContextSensitiveFunctionLikeDeclaration(node: FunctionLikeDeclaration) { - if (compilerOptions.strictThis) { - return !node.typeParameters && - (!forEach(node.parameters, p => p.type) - || (node.kind !== SyntaxKind.ArrowFunction && (!node.parameters.length || (node.parameters[0].name).text !== "this"))); - } - else { - return !node.typeParameters && node.parameters.length && !forEach(node.parameters, p => p.type); + const areAllParametersUntyped = !forEach(node.parameters, p => p.type); + if (node.kind === SyntaxKind.ArrowFunction) { + return !node.typeParameters && node.parameters.length && areAllParametersUntyped; } + const hasThisType = node.parameters.length && (node.parameters[0].name).text === "this" && node.parameters[0].type; + return !node.typeParameters && areAllParametersUntyped && !hasThisType; } function getTypeWithoutSignatures(type: Type): Type { @@ -5305,13 +5302,13 @@ namespace ts { let result = Ternary.True; if (source.thisType || target.thisType) { - const s = source.thisType || anyType; - const t = target.thisType || anyType; - if (s !== voidType) { + if (source.thisType !== voidType) { + const s = source.thisType ? getApparentType(source.thisType) : anyType; + const t = target.thisType ? getApparentType(target.thisType) : anyType; // void sources are assignable to anything. - let related = compareTypes(getApparentType(t), getApparentType(s), reportErrors); + let related = compareTypes(t, s, reportErrors); if (!related) { - related = compareTypes(getApparentType(s), getApparentType(t), /*reportErrors*/ false); + related = compareTypes(s, t, /*reportErrors*/ false); if (!related) { errorReporter(Diagnostics.Types_of_parameters_0_and_1_are_incompatible, "this", "this"); return Ternary.False; @@ -11626,6 +11623,11 @@ namespace ts { if (node.questionToken && isBindingPattern(node.name) && func.body) { error(node, Diagnostics.A_binding_pattern_parameter_cannot_be_optional_in_an_implementation_signature); } + if ((node.name).text === "this") { + if(indexOf(func.parameters, node) !== 0 || func.kind === SyntaxKind.Constructor) { + error(node, Diagnostics.this_cannot_be_referenced_in_current_location); + } + } // Only check rest parameter type if it's not a binding pattern. Since binding patterns are // not allowed in a rest parameter, we already have an error from checkGrammarParameterList. diff --git a/tests/baselines/reference/contextualTyping24.errors.txt b/tests/baselines/reference/contextualTyping24.errors.txt index a172600e1c5..b4d0d534456 100644 --- a/tests/baselines/reference/contextualTyping24.errors.txt +++ b/tests/baselines/reference/contextualTyping24.errors.txt @@ -4,7 +4,7 @@ tests/cases/compiler/contextualTyping24.ts(1,55): error TS2322: Type '(a: string ==== tests/cases/compiler/contextualTyping24.ts (1 errors) ==== - var foo:(a:{():number; (i:number):number; })=>number; foo = function(a:string){return 5}; + var foo:(a:{():number; (i:number):number; })=>number; foo = function(this: void, a:string){return 5}; ~~~ !!! error TS2322: Type '(a: string) => number' is not assignable to type '(a: { (): number; (i: number): number; }) => number'. !!! error TS2322: Types of parameters 'a' and 'a' are incompatible. diff --git a/tests/baselines/reference/contextualTyping24.js b/tests/baselines/reference/contextualTyping24.js index 04c4ecba21b..14c1feeb031 100644 --- a/tests/baselines/reference/contextualTyping24.js +++ b/tests/baselines/reference/contextualTyping24.js @@ -1,5 +1,5 @@ //// [contextualTyping24.ts] -var foo:(a:{():number; (i:number):number; })=>number; foo = function(a:string){return 5}; +var foo:(a:{():number; (i:number):number; })=>number; foo = function(this: void, a:string){return 5}; //// [contextualTyping24.js] var foo; diff --git a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt index 058a1555ed6..317446050a8 100644 --- a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt +++ b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt @@ -1,11 +1,15 @@ -tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(20,1): error TS2322: Type '(this: C, m: number) => number' is not assignable to type '(m: number) => number'. +tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(21,1): error TS2322: Type '(this: C, m: number) => number' is not assignable to type '(m: number) => number'. Types of parameters 'this' and 'this' are incompatible. Type 'void' is not assignable to type 'C'. -tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(27,9): error TS2345: Argument of type 'void' is not assignable to parameter of type 'I'. +tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(32,5): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(33,27): error TS2339: Property 'length' does not exist on type 'number'. +tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(37,9): error TS2345: Argument of type 'void' is not assignable to parameter of type 'I'. +tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(46,19): error TS2339: Property 'length' does not exist on type 'number'. -==== tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts (2 errors) ==== +==== tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts (5 errors) ==== interface I { + n: number; explicitThis(this: this, m: number): number; } interface Unused { @@ -30,10 +34,23 @@ tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(27,9): error !!! error TS2322: Types of parameters 'this' and 'this' are incompatible. !!! error TS2322: Type 'void' is not assignable to type 'C'. let o = { - explicitThis: function (m) { return m }, - implicitThis(m: number): number { return m } + n: 101, + explicitThis: function (m: number) { + return m + this.n.length; // ok, this.n: any + }, + implicitThis(m: number): number { return m; } }; let i: I = o; + let o2: I = { + n: 1001 + explicitThis: function (m) { + ~~~~~~~~~~~~ +!!! error TS1005: ',' expected. + return m + this.n.length; // error, this.n: number, no member 'length' + ~~~~~~ +!!! error TS2339: Property 'length' does not exist on type 'number'. + }, + } let x = i.explicitThis; let n = x(12); // callee:void doesn't match this:I ~~~~~ @@ -45,4 +62,9 @@ tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(27,9): error o.implicitThis = c.implicitThis; // ok, implicitThis(this:any) o.implicitThis = c.explicitThis; // ok, implicitThis(this:any) is assignable to explicitThis(this: this) o.implicitThis = i.explicitThis; + i.explicitThis = function(m) { + return this.n.length; // error, this.n: number + ~~~~~~ +!!! error TS2339: Property 'length' does not exist on type 'number'. + } \ No newline at end of file diff --git a/tests/baselines/reference/looseThisTypeInFunctions.js b/tests/baselines/reference/looseThisTypeInFunctions.js index 66677293c5b..ecb9f650716 100644 --- a/tests/baselines/reference/looseThisTypeInFunctions.js +++ b/tests/baselines/reference/looseThisTypeInFunctions.js @@ -1,5 +1,6 @@ //// [looseThisTypeInFunctions.ts] interface I { + n: number; explicitThis(this: this, m: number): number; } interface Unused { @@ -20,10 +21,19 @@ class C implements I { let c = new C(); c.explicitVoid = c.explicitThis; // error, 'void' is missing everything let o = { - explicitThis: function (m) { return m }, - implicitThis(m: number): number { return m } + n: 101, + explicitThis: function (m: number) { + return m + this.n.length; // ok, this.n: any + }, + implicitThis(m: number): number { return m; } }; let i: I = o; +let o2: I = { + n: 1001 + explicitThis: function (m) { + return m + this.n.length; // error, this.n: number, no member 'length' + }, +} let x = i.explicitThis; let n = x(12); // callee:void doesn't match this:I let u: Unused; @@ -33,6 +43,9 @@ c.explicitVoid = c.implicitThis // ok, implicitThis(this:any) o.implicitThis = c.implicitThis; // ok, implicitThis(this:any) o.implicitThis = c.explicitThis; // ok, implicitThis(this:any) is assignable to explicitThis(this: this) o.implicitThis = i.explicitThis; +i.explicitThis = function(m) { + return this.n.length; // error, this.n: number +} //// [looseThisTypeInFunctions.js] @@ -53,10 +66,19 @@ var C = (function () { var c = new C(); c.explicitVoid = c.explicitThis; // error, 'void' is missing everything var o = { - explicitThis: function (m) { return m; }, + n: 101, + explicitThis: function (m) { + return m + this.n.length; // ok, this.n: any + }, implicitThis: function (m) { return m; } }; var i = o; +var o2 = { + n: 1001, + explicitThis: function (m) { + return m + this.n.length; // error, this.n: number, no member 'length' + } +}; var x = i.explicitThis; var n = x(12); // callee:void doesn't match this:I var u; @@ -66,3 +88,6 @@ c.explicitVoid = c.implicitThis; // ok, implicitThis(this:any) o.implicitThis = c.implicitThis; // ok, implicitThis(this:any) o.implicitThis = c.explicitThis; // ok, implicitThis(this:any) is assignable to explicitThis(this: this) o.implicitThis = i.explicitThis; +i.explicitThis = function (m) { + return this.n.length; // error, this.n: number +}; diff --git a/tests/baselines/reference/thisTypeInFunctions.js b/tests/baselines/reference/thisTypeInFunctions.js index 0798843fc44..f3ad84acb55 100644 --- a/tests/baselines/reference/thisTypeInFunctions.js +++ b/tests/baselines/reference/thisTypeInFunctions.js @@ -140,10 +140,10 @@ c.explicitThis = explicitCFunction; c.explicitThis = function(this: C, m: number) { return this.n + m }; // this:any compatibility -c.explicitC = function(m: number) { return this.n + m }; -c.explicitProperty = function(m: number) { return this.n + m }; -c.explicitThis = function(m: number) { return this.n + m }; -c.implicitThis = function(m: number) { return this.n + m }; +c.explicitC = function(m) { return this.n + m }; +c.explicitProperty = function(m) { return this.n + m }; +c.explicitThis = function(m) { return this.n + m }; +c.implicitThis = function(m) { return this.n + m }; c.implicitThis = reconstructed.implicitThis; c.explicitC = function(this: B, m: number) { return this.n + m }; diff --git a/tests/baselines/reference/thisTypeInFunctions.symbols b/tests/baselines/reference/thisTypeInFunctions.symbols index 1d9ebbd0cf4..bb6a9acfdd0 100644 --- a/tests/baselines/reference/thisTypeInFunctions.symbols +++ b/tests/baselines/reference/thisTypeInFunctions.symbols @@ -585,7 +585,7 @@ c.explicitThis = function(this: C, m: number) { return this.n + m }; >m : Symbol(m, Decl(thisTypeInFunctions.ts, 138, 34)) // this:any compatibility -c.explicitC = function(m: number) { return this.n + m }; +c.explicitC = function(m) { return this.n + m }; >c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) >explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) @@ -595,7 +595,7 @@ c.explicitC = function(m: number) { return this.n + m }; >n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 141, 23)) -c.explicitProperty = function(m: number) { return this.n + m }; +c.explicitProperty = function(m) { return this.n + m }; >c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) >explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) @@ -605,7 +605,7 @@ c.explicitProperty = function(m: number) { return this.n + m }; >n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 142, 30)) -c.explicitThis = function(m: number) { return this.n + m }; +c.explicitThis = function(m) { return this.n + m }; >c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) >explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) @@ -615,7 +615,7 @@ c.explicitThis = function(m: number) { return this.n + m }; >n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 143, 26)) -c.implicitThis = function(m: number) { return this.n + m }; +c.implicitThis = function(m) { return this.n + m }; >c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) >implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) diff --git a/tests/baselines/reference/thisTypeInFunctions.types b/tests/baselines/reference/thisTypeInFunctions.types index 36b458b91e0..b0fc9fc3300 100644 --- a/tests/baselines/reference/thisTypeInFunctions.types +++ b/tests/baselines/reference/thisTypeInFunctions.types @@ -520,7 +520,7 @@ let anyToSpecified: (this: { y: number }, x: number) => number = function(x: num >this : { y: number; } >y : number >x : number ->function(x: number): number { return x + 12; } : (this: { y: number; }, x: number) => number +>function(x: number): number { return x + 12; } : (x: number) => number >x : number >x + 12 : number >x : number @@ -718,12 +718,12 @@ c.explicitThis = function(this: C, m: number) { return this.n + m }; >m : number // this:any compatibility -c.explicitC = function(m: number) { return this.n + m }; ->c.explicitC = function(m: number) { return this.n + m } : (this: C, m: number) => number +c.explicitC = function(m) { return this.n + m }; +>c.explicitC = function(m) { return this.n + m } : (this: C, m: number) => number >c.explicitC : (this: C, m: number) => number >c : C >explicitC : (this: C, m: number) => number ->function(m: number) { return this.n + m } : (this: C, m: number) => number +>function(m) { return this.n + m } : (this: C, m: number) => number >m : number >this.n + m : number >this.n : number @@ -731,12 +731,12 @@ c.explicitC = function(m: number) { return this.n + m }; >n : number >m : number -c.explicitProperty = function(m: number) { return this.n + m }; ->c.explicitProperty = function(m: number) { return this.n + m } : (this: { n: number; }, m: number) => number +c.explicitProperty = function(m) { return this.n + m }; +>c.explicitProperty = function(m) { return this.n + m } : (this: { n: number; }, m: number) => number >c.explicitProperty : (this: { n: number; }, m: number) => number >c : C >explicitProperty : (this: { n: number; }, m: number) => number ->function(m: number) { return this.n + m } : (this: { n: number; }, m: number) => number +>function(m) { return this.n + m } : (this: { n: number; }, m: number) => number >m : number >this.n + m : number >this.n : number @@ -744,12 +744,12 @@ c.explicitProperty = function(m: number) { return this.n + m }; >n : number >m : number -c.explicitThis = function(m: number) { return this.n + m }; ->c.explicitThis = function(m: number) { return this.n + m } : (this: C, m: number) => number +c.explicitThis = function(m) { return this.n + m }; +>c.explicitThis = function(m) { return this.n + m } : (this: C, m: number) => number >c.explicitThis : (this: C, m: number) => number >c : C >explicitThis : (this: C, m: number) => number ->function(m: number) { return this.n + m } : (this: C, m: number) => number +>function(m) { return this.n + m } : (this: C, m: number) => number >m : number >this.n + m : number >this.n : number @@ -757,12 +757,12 @@ c.explicitThis = function(m: number) { return this.n + m }; >n : number >m : number -c.implicitThis = function(m: number) { return this.n + m }; ->c.implicitThis = function(m: number) { return this.n + m } : (this: C, m: number) => number +c.implicitThis = function(m) { return this.n + m }; +>c.implicitThis = function(m) { return this.n + m } : (this: C, m: number) => number >c.implicitThis : (this: C, m: number) => number >c : C >implicitThis : (this: C, m: number) => number ->function(m: number) { return this.n + m } : (this: C, m: number) => number +>function(m) { return this.n + m } : (this: C, m: number) => number >m : number >this.n + m : number >this.n : number diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt index ce3b3eed6f8..4e8efd187eb 100644 --- a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt @@ -94,6 +94,7 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(170,1): er tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(179,16): error TS2672: A function that is called with the 'new' keyword cannot have a 'this' type that is void. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(180,24): error TS2672: A function that is called with the 'new' keyword cannot have a 'this' type that is void. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(184,30): error TS2332: 'this' cannot be referenced in current location. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(184,61): error TS2339: Property 'n' does not exist on type 'void'. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(185,26): error TS1003: Identifier expected. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(185,30): error TS1005: ',' expected. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(185,57): error TS2339: Property 'n' does not exist on type 'void'. @@ -103,7 +104,6 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(186,27): e tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(186,54): error TS2339: Property 'n' does not exist on type 'void'. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(187,23): error TS1005: ',' expected. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(187,24): error TS1138: Parameter declaration expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(187,51): error TS2339: Property 'n' does not exist on type 'void'. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(188,28): error TS1003: Identifier expected. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(188,32): error TS1005: ',' expected. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(188,59): error TS2339: Property 'n' does not exist on type 'void'. @@ -452,6 +452,8 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,35): e function notFirst(a: number, this: C): number { return this.n; } ~~~~~~~ !!! error TS2332: 'this' cannot be referenced in current location. + ~ +!!! error TS2339: Property 'n' does not exist on type 'void'. function modifiers(async this: C): number { return this.n; } ~~~~ !!! error TS1003: Identifier expected. @@ -473,8 +475,6 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,35): e !!! error TS1005: ',' expected. ~ !!! error TS1138: Parameter declaration expected. - ~ -!!! error TS2339: Property 'n' does not exist on type 'void'. function decorated(@deco() this: C): number { return this.n; } ~~~~ !!! error TS1003: Identifier expected. diff --git a/tests/cases/compiler/contextualTyping24.ts b/tests/cases/compiler/contextualTyping24.ts index be28ff3b04c..fad23fa313c 100644 --- a/tests/cases/compiler/contextualTyping24.ts +++ b/tests/cases/compiler/contextualTyping24.ts @@ -1 +1 @@ -var foo:(a:{():number; (i:number):number; })=>number; foo = function(a:string){return 5}; \ No newline at end of file +var foo:(a:{():number; (i:number):number; })=>number; foo = function(this: void, a:string){return 5}; \ No newline at end of file diff --git a/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts index 34d1ebd4a8e..3e8bdb11170 100644 --- a/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts +++ b/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts @@ -1,4 +1,5 @@ interface I { + n: number; explicitThis(this: this, m: number): number; } interface Unused { @@ -19,10 +20,19 @@ class C implements I { let c = new C(); c.explicitVoid = c.explicitThis; // error, 'void' is missing everything let o = { - explicitThis: function (m) { return m }, - implicitThis(m: number): number { return m } + n: 101, + explicitThis: function (m: number) { + return m + this.n.length; // ok, this.n: any + }, + implicitThis(m: number): number { return m; } }; let i: I = o; +let o2: I = { + n: 1001 + explicitThis: function (m) { + return m + this.n.length; // error, this.n: number, no member 'length' + }, +} let x = i.explicitThis; let n = x(12); // callee:void doesn't match this:I let u: Unused; @@ -32,3 +42,6 @@ c.explicitVoid = c.implicitThis // ok, implicitThis(this:any) o.implicitThis = c.implicitThis; // ok, implicitThis(this:any) o.implicitThis = c.explicitThis; // ok, implicitThis(this:any) is assignable to explicitThis(this: this) o.implicitThis = i.explicitThis; +i.explicitThis = function(m) { + return this.n.length; // error, this.n: number +} diff --git a/tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts b/tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts new file mode 100644 index 00000000000..2f4873031fb --- /dev/null +++ b/tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts @@ -0,0 +1,27 @@ +// @strictThis: true +// 1. contextual typing predicate is wrong (currently: method2: function () ...) +// () -> yes (allParametersAreUntyped=t, noThisParameter=t, noTypeParameters=t) +// ok .. fixed? +// 2. contextual typing of this doesn't seem to work +// strictThis was turned off. DUH. +// 3. when it DID work, it was giving bogus types with strictThis OFF (see the last example) +interface T { + (x: number): void; +} +interface I { + n: number + method(this: this): number; + method2(this: this): number; +} +let i: I = { + n: 12, + method: function(this) { // this: I + return this.n.length; // error, 'number' has no property 'length' + }, + method2: function() { // this: I + return this.n.length; // error, 'number' has no property 'length' + } +} +i.method = function () { return this.n.length } // this: I +i.method = function (this) { return this.n.length } // this: I +var t: T = function (this, y) { } // yes! (but this: any NOT number!!) \ No newline at end of file diff --git a/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts index 623c880d339..f92b8ab4e15 100644 --- a/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts +++ b/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts @@ -140,10 +140,10 @@ c.explicitThis = explicitCFunction; c.explicitThis = function(this: C, m: number) { return this.n + m }; // this:any compatibility -c.explicitC = function(m: number) { return this.n + m }; -c.explicitProperty = function(m: number) { return this.n + m }; -c.explicitThis = function(m: number) { return this.n + m }; -c.implicitThis = function(m: number) { return this.n + m }; +c.explicitC = function(m) { return this.n + m }; +c.explicitProperty = function(m) { return this.n + m }; +c.explicitThis = function(m) { return this.n + m }; +c.implicitThis = function(m) { return this.n + m }; c.implicitThis = reconstructed.implicitThis; c.explicitC = function(this: B, m: number) { return this.n + m }; From 2f74da112db6491d53321dc947660fb7c3f8e5d3 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 4 Feb 2016 16:01:10 -0800 Subject: [PATCH 036/274] Add specific error messages for out-of-place this Also remove lint in checker. --- src/compiler/checker.ts | 7 +- src/compiler/diagnosticMessages.json | 8 +++ .../thisTypeInFunctionsNegative.errors.txt | 64 +++++++++++-------- .../reference/thisTypeInFunctionsNegative.js | 16 ++++- .../thisType/thisTypeInFunctionsNegative.ts | 7 +- 5 files changed, 69 insertions(+), 33 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2303aa539f6..4508b25383f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11624,8 +11624,11 @@ namespace ts { error(node, Diagnostics.A_binding_pattern_parameter_cannot_be_optional_in_an_implementation_signature); } if ((node.name).text === "this") { - if(indexOf(func.parameters, node) !== 0 || func.kind === SyntaxKind.Constructor) { - error(node, Diagnostics.this_cannot_be_referenced_in_current_location); + if (indexOf(func.parameters, node) !== 0) { + error(node, Diagnostics.this_parameter_must_be_the_first_parameter); + } + if (func.kind === SyntaxKind.Constructor) { + error(node, Diagnostics.A_constructor_cannot_have_a_this_parameter); } } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 804b820f11e..116270d0c4d 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1827,6 +1827,14 @@ "category": "Error", "code": 2672 }, + "'this' parameter must be the first parameter.": { + "category": "Error", + "code": 2673 + }, + "A constructor cannot have a 'this' parameter.": { + "category": "Error", + "code": 2674 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", "code": 4000 diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt index 4e8efd187eb..0b755b9e0bd 100644 --- a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt @@ -93,33 +93,34 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(170,1): er Type 'Base1' is not assignable to type 'Base2'. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(179,16): error TS2672: A function that is called with the 'new' keyword cannot have a 'this' type that is void. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(180,24): error TS2672: A function that is called with the 'new' keyword cannot have a 'this' type that is void. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(184,30): error TS2332: 'this' cannot be referenced in current location. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(184,61): error TS2339: Property 'n' does not exist on type 'void'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(185,26): error TS1003: Identifier expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(185,30): error TS1005: ',' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(185,57): error TS2339: Property 'n' does not exist on type 'void'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(186,20): error TS2370: A rest parameter must be of an array type. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(186,23): error TS1003: Identifier expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(186,27): error TS1005: ',' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(186,54): error TS2339: Property 'n' does not exist on type 'void'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(187,23): error TS1005: ',' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(187,24): error TS1138: Parameter declaration expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(188,28): error TS1003: Identifier expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(188,32): error TS1005: ',' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(188,59): error TS2339: Property 'n' does not exist on type 'void'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,30): error TS1005: ',' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,32): error TS1138: Parameter declaration expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,39): error TS1005: ';' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,40): error TS1128: Declaration or statement expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,42): error TS2304: Cannot find name 'number'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(189,49): error TS1005: ';' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,1): error TS7027: Unreachable code detected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,29): error TS2304: Cannot find name 'm'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,32): error TS1005: ';' expected. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,35): error TS2304: Cannot find name 'm'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(184,17): error TS2674: A constructor cannot have a 'this' parameter. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(187,30): error TS2673: 'this' parameter must be the first parameter. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(187,61): error TS2339: Property 'n' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(190,26): error TS1003: Identifier expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(190,30): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(190,57): error TS2339: Property 'n' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(191,20): error TS2370: A rest parameter must be of an array type. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(191,23): error TS1003: Identifier expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(191,27): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(191,54): error TS2339: Property 'n' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,23): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,24): error TS1138: Parameter declaration expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(193,28): error TS1003: Identifier expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(193,32): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(193,59): error TS2339: Property 'n' does not exist on type 'void'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(194,30): error TS1005: ',' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(194,32): error TS1138: Parameter declaration expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(194,39): error TS1005: ';' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(194,40): error TS1128: Declaration or statement expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(194,42): error TS2304: Cannot find name 'number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(194,49): error TS1005: ';' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,1): error TS7027: Unreachable code detected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,29): error TS2304: Cannot find name 'm'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,32): error TS1005: ';' expected. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,35): error TS2304: Cannot find name 'm'. -==== tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts (75 errors) ==== +==== tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts (76 errors) ==== class C { n: number; explicitThis(this: this, m: number): number { @@ -447,13 +448,20 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(192,35): e ~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2672: A function that is called with the 'new' keyword cannot have a 'this' type that is void. - - ///// parse errors ///// + ///// syntax-ish errors ///// + class ThisConstructor { + constructor(this: ThisConstructor, private n: number) { + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2674: A constructor cannot have a 'this' parameter. + } + } function notFirst(a: number, this: C): number { return this.n; } ~~~~~~~ -!!! error TS2332: 'this' cannot be referenced in current location. +!!! error TS2673: 'this' parameter must be the first parameter. ~ !!! error TS2339: Property 'n' does not exist on type 'void'. + + ///// parse errors ///// function modifiers(async this: C): number { return this.n; } ~~~~ !!! error TS1003: Identifier expected. diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.js b/tests/baselines/reference/thisTypeInFunctionsNegative.js index 43d83daef0d..c0892d9e4c8 100644 --- a/tests/baselines/reference/thisTypeInFunctionsNegative.js +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.js @@ -180,9 +180,14 @@ function ImplicitVoidThis() { let voidThis = new VoidThis(); let implicitVoidThis = new ImplicitVoidThis(); +///// syntax-ish errors ///// +class ThisConstructor { + constructor(this: ThisConstructor, private n: number) { + } +} +function notFirst(a: number, this: C): number { return this.n; } ///// parse errors ///// -function notFirst(a: number, this: C): number { return this.n; } function modifiers(async this: C): number { return this.n; } function restParam(...this: C): number { return this.n; } function optional(this?: C): number { return this.n; } @@ -364,8 +369,15 @@ function ImplicitVoidThis() { } var voidThis = new VoidThis(); var implicitVoidThis = new ImplicitVoidThis(); -///// parse errors ///// +///// syntax-ish errors ///// +var ThisConstructor = (function () { + function ThisConstructor(n) { + this.n = n; + } + return ThisConstructor; +}()); function notFirst(a, this) { return this.n; } +///// parse errors ///// function modifiers(, C) { if ( === void 0) { = this; } return this.n; diff --git a/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts b/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts index 3fba9ad8a73..3afc5a5c69b 100644 --- a/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts +++ b/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts @@ -180,9 +180,14 @@ function ImplicitVoidThis() { let voidThis = new VoidThis(); let implicitVoidThis = new ImplicitVoidThis(); +///// syntax-ish errors ///// +class ThisConstructor { + constructor(this: ThisConstructor, private n: number) { + } +} +function notFirst(a: number, this: C): number { return this.n; } ///// parse errors ///// -function notFirst(a: number, this: C): number { return this.n; } function modifiers(async this: C): number { return this.n; } function restParam(...this: C): number { return this.n; } function optional(this?: C): number { return this.n; } From 71488fc3b1b75202efceb9b93ad84e571cad07cf Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 5 Feb 2016 09:38:17 -0800 Subject: [PATCH 037/274] Refactorings from review comments 1. Add `getThisArgumentOfCall` (and correct the code) 2. Remove `getParameterTypeAtIndex` in favour of `getTypeAtPosition`. Simplify calling code. --- src/compiler/checker.ts | 61 ++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4508b25383f..f595a588dd7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3559,10 +3559,6 @@ namespace ts { sig.minArgumentCount, sig.hasRestParameter, sig.hasStringLiterals); } - function getParameterTypeAtIndex(signature: Signature, i: number, max: number, outOfRangeType?: Type): Type { - return i < max ? getTypeOfSymbol(signature.parameters[i]) : (outOfRangeType || getRestTypeOfSignature(signature)); - } - function getDefaultConstructSignatures(classType: InterfaceType): Signature[] { const baseConstructorType = getBaseConstructorTypeOfClass(classType); const baseSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct); @@ -5301,14 +5297,12 @@ namespace ts { target = getErasedSignature(target); let result = Ternary.True; - if (source.thisType || target.thisType) { + if (source.thisType && target.thisType) { if (source.thisType !== voidType) { - const s = source.thisType ? getApparentType(source.thisType) : anyType; - const t = target.thisType ? getApparentType(target.thisType) : anyType; // void sources are assignable to anything. - let related = compareTypes(t, s, reportErrors); + let related = compareTypes(target.thisType, source.thisType, reportErrors); if (!related) { - related = compareTypes(s, t, /*reportErrors*/ false); + related = compareTypes(source.thisType, target.thisType, /*reportErrors*/ false); if (!related) { errorReporter(Diagnostics.Types_of_parameters_0_and_1_are_incompatible, "this", "this"); return Ternary.False; @@ -6474,27 +6468,23 @@ namespace ts { } function forEachMatchingParameterType(source: Signature, target: Signature, callback: (s: Type, t: Type) => void) { - let sourceMax = source.parameters.length; - let targetMax = target.parameters.length; + const sourceMax = source.parameters.length; + const targetMax = target.parameters.length; let count: number; if (source.hasRestParameter && target.hasRestParameter) { - count = sourceMax > targetMax ? sourceMax : targetMax; - sourceMax--; - targetMax--; + count = Math.max(sourceMax, targetMax); } else if (source.hasRestParameter) { - sourceMax--; count = targetMax; } else if (target.hasRestParameter) { - targetMax--; count = sourceMax; } else { - count = sourceMax < targetMax ? sourceMax : targetMax; + count = Math.min(sourceMax, targetMax); } for (let i = 0; i < count; i++) { - callback(getParameterTypeAtIndex(source, i, sourceMax), getParameterTypeAtIndex(target, i, targetMax)); + callback(getTypeAtPosition(source, i), getTypeAtPosition(target, i)); } } @@ -9416,7 +9406,7 @@ namespace ts { context.failedTypeParameterIndex = undefined; } - const calleeNode = node.kind === SyntaxKind.CallExpression && ((node).expression).expression; + const calleeNode = getThisArgumentOfCall(node); if (signature.thisType) { const mapper = excludeCallee !== undefined ? identityMapper : inferenceMapper; const calleeType: Type = calleeNode ? checkExpressionWithContextualType(calleeNode, signature.thisType, mapper) : voidType; @@ -9503,13 +9493,13 @@ namespace ts { function checkApplicableSignature(node: CallLikeExpression, args: Expression[], signature: Signature, relation: Map, excludeArgument: boolean[], reportErrors: boolean) { const headMessage = Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1; if (signature.thisType && signature.thisType !== voidType && node.kind !== SyntaxKind.NewExpression) { - // If the source is not of the form `x.f`, then sourceType = voidType - // If the target is voidType, then the check is skipped -- anything is compatible. - // If the the expression is a new expression, then the check is skipped. - const calleeNode = node.kind === SyntaxKind.CallExpression && ((node).expression).expression; - const calleeType: Type = calleeNode ? checkExpressionWithContextualType(calleeNode, signature.thisType, undefined) : voidType; + // If the source's this is not of the form `x.f` or `x[f]`, then sourceType = voidType + // If the target's this is voidType, then the check is skipped -- anything is compatible. + // If the expression is a new expression, then the check is skipped. + const calleeNode = getThisArgumentOfCall(node); + const calleeType = calleeNode ? checkExpression(calleeNode) : voidType; const errorNode = reportErrors ? (calleeNode || node) : undefined; - if (!checkTypeRelatedTo(calleeType, getApparentType(signature.thisType), relation, errorNode, headMessage)) { + if (!checkTypeRelatedTo(calleeType, signature.thisType, relation, errorNode, headMessage)) { return false; } } @@ -9541,6 +9531,21 @@ namespace ts { return true; } + /** + * Returns the this argument in calls like x.f(...) and x[f](...). Undefined otherwise. + */ + function getThisArgumentOfCall(node: CallLikeExpression): LeftHandSideExpression { + if (node.kind === SyntaxKind.CallExpression) { + const callee = (node).expression; + if (callee.kind === SyntaxKind.PropertyAccessExpression) { + return (callee as PropertyAccessExpression).expression; + } + else if (callee.kind === SyntaxKind.ElementAccessExpression) { + return (callee as ElementAccessExpression).expression; + } + } + } + /** * Returns the effective arguments for an expression that works like a function invocation. * @@ -9888,7 +9893,7 @@ namespace ts { let excludeCallee: boolean; let excludeArgument: boolean[]; if (!isDecorator) { - const calleeNode = node.kind === SyntaxKind.CallExpression && ((node).expression).expression; + const calleeNode = getThisArgumentOfCall(node); if (calleeNode && isContextSensitive(calleeNode)) { excludeCallee = true; } @@ -10397,8 +10402,8 @@ namespace ts { function getTypeAtPosition(signature: Signature, pos: number): Type { return signature.hasRestParameter ? - getParameterTypeAtIndex(signature, pos, signature.parameters.length - 1) : - getParameterTypeAtIndex(signature, pos, signature.parameters.length, anyType); + pos < signature.parameters.length - 1 ? getTypeOfSymbol(signature.parameters[pos]) : getRestTypeOfSignature(signature) : + pos < signature.parameters.length ? getTypeOfSymbol(signature.parameters[pos]) : anyType; } function assignContextualParameterTypes(signature: Signature, context: Signature, mapper: TypeMapper) { From 5821b87eda234e51f8822a6783f2f1864863b2a8 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 5 Feb 2016 13:53:33 -0800 Subject: [PATCH 038/274] Do not contextually type object callee arguments --- src/compiler/checker.ts | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f595a588dd7..32e82d9d537 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9380,7 +9380,7 @@ namespace ts { return getSignatureInstantiation(signature, getInferredTypes(context)); } - function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: Expression[], excludeCallee: boolean, excludeArgument: boolean[], context: InferenceContext): void { + function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: Expression[], excludeArgument: boolean[], context: InferenceContext): void { const typeParameters = signature.typeParameters; const inferenceMapper = getInferenceMapper(context); @@ -9406,11 +9406,10 @@ namespace ts { context.failedTypeParameterIndex = undefined; } - const calleeNode = getThisArgumentOfCall(node); if (signature.thisType) { - const mapper = excludeCallee !== undefined ? identityMapper : inferenceMapper; - const calleeType: Type = calleeNode ? checkExpressionWithContextualType(calleeNode, signature.thisType, mapper) : voidType; - inferTypes(context, calleeType, signature.thisType); + const thisArgumentNode = getThisArgumentOfCall(node); + const thisArgumentType = thisArgumentNode ? checkExpression(thisArgumentNode) : voidType; + inferTypes(context, thisArgumentType, signature.thisType); } // We perform two passes over the arguments. In the first pass we infer from all arguments, but use @@ -9442,11 +9441,6 @@ namespace ts { // Decorators will not have `excludeArgument`, as their arguments cannot be contextually typed. // Tagged template expressions will always have `undefined` for `excludeArgument[0]`. if (excludeArgument) { - if (signature.thisType && calleeNode) { - if (excludeCallee === false) { - inferTypes(context, checkExpressionWithContextualType(calleeNode, signature.thisType, inferenceMapper), signature.thisType); - } - } for (let i = 0; i < argCount; i++) { // No need to check for omitted args and template expressions, their exclusion value is always undefined if (excludeArgument[i] === false) { @@ -9496,10 +9490,10 @@ namespace ts { // If the source's this is not of the form `x.f` or `x[f]`, then sourceType = voidType // If the target's this is voidType, then the check is skipped -- anything is compatible. // If the expression is a new expression, then the check is skipped. - const calleeNode = getThisArgumentOfCall(node); - const calleeType = calleeNode ? checkExpression(calleeNode) : voidType; - const errorNode = reportErrors ? (calleeNode || node) : undefined; - if (!checkTypeRelatedTo(calleeType, signature.thisType, relation, errorNode, headMessage)) { + const thisArgumentNode = getThisArgumentOfCall(node); + const thisArgumentType = thisArgumentNode ? checkExpression(thisArgumentNode) : voidType; + const errorNode = reportErrors ? (thisArgumentNode || node) : undefined; + if (!checkTypeRelatedTo(thisArgumentType, signature.thisType, relation, errorNode, headMessage)) { return false; } } @@ -9890,13 +9884,8 @@ namespace ts { // // For a decorator, no arguments are susceptible to contextual typing due to the fact // decorators are applied to a declaration by the emitter, and not to an expression. - let excludeCallee: boolean; let excludeArgument: boolean[]; if (!isDecorator) { - const calleeNode = getThisArgumentOfCall(node); - if (calleeNode && isContextSensitive(calleeNode)) { - excludeCallee = true; - } // We do not need to call `getEffectiveArgumentCount` here as it only // applies when calculating the number of arguments for a decorator. for (let i = isTaggedTemplate ? 1 : 0; i < args.length; i++) { @@ -10045,7 +10034,7 @@ namespace ts { typeArgumentsAreValid = checkTypeArguments(candidate, typeArguments, typeArgumentTypes, /*reportErrors*/ false); } else { - inferTypeArguments(node, candidate, args, excludeCallee, excludeArgument, inferenceContext); + inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); typeArgumentsAreValid = inferenceContext.failedTypeParameterIndex === undefined; typeArgumentTypes = inferenceContext.inferredTypes; } From 80de700be03700f483d1852a130f490a266e66b4 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 5 Feb 2016 16:18:21 -0800 Subject: [PATCH 039/274] Get contextual type of this parameter correctly Now the language service also sees the contextual type. Note that with this change, the type display for contextually typed this parameters goes away because there is no symbol. I'll fix type display next. --- src/compiler/checker.ts | 23 +++++++--- .../reference/thisTypeInFunctions.types | 42 +++++++++---------- tests/cases/fourslash/quickInfoOnThis.ts | 16 ++++++- 3 files changed, 53 insertions(+), 28 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 32e82d9d537..be98dc985b5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7383,6 +7383,10 @@ namespace ts { captureLexicalThis(node, container); } if (isFunctionLike(container)) { + const type = getContextuallyTypedThisType(container); + if (type) { + return type; + } const signature = getSignatureFromDeclaration(container); if (signature.thisType) { return signature.thisType; @@ -7633,6 +7637,19 @@ namespace ts { } } + function getContextuallyTypedThisType(func: FunctionLikeDeclaration): Type { + if ((isFunctionExpressionOrArrowFunction(func) || isObjectLiteralMethod(func)) && + isContextSensitive(func) && + func.kind !== SyntaxKind.ArrowFunction) { + const contextualSignature = getContextualSignature(func); + if (contextualSignature) { + return contextualSignature.thisType; + } + } + + return undefined; + } + // Return contextual type of parameter or undefined if no contextual type is available function getContextuallyTypedParameterType(parameter: ParameterDeclaration): Type { const func = parameter.parent; @@ -10396,12 +10413,6 @@ namespace ts { } function assignContextualParameterTypes(signature: Signature, context: Signature, mapper: TypeMapper) { - if (context.thisType) { - if (signature.declaration.kind !== SyntaxKind.ArrowFunction) { - // do not contextually type thisType for ArrowFunction. - signature.thisType = context.thisType; - } - } const len = signature.parameters.length - (signature.hasRestParameter ? 1 : 0); for (let i = 0; i < len; i++) { const parameter = signature.parameters[i]; diff --git a/tests/baselines/reference/thisTypeInFunctions.types b/tests/baselines/reference/thisTypeInFunctions.types index b0fc9fc3300..e1044bb3d90 100644 --- a/tests/baselines/reference/thisTypeInFunctions.types +++ b/tests/baselines/reference/thisTypeInFunctions.types @@ -143,7 +143,7 @@ function implicitThis(n: number): number { let impl: I = { >impl : I >I : I ->{ a: 12, explicitVoid2: () => this.a, // ok, this: any because it refers to some outer object (window?) explicitVoid1() { return 12; }, explicitStructural() { return this.a; }, explicitInterface() { return this.a; }, explicitThis() { return this.a; }, implicitMethod() { return this.a; }, implicitFunction: () => this.a, // ok, this: any because it refers to some outer object (window?)} : { a: number; explicitVoid2: () => any; explicitVoid1(): number; explicitStructural(this: { a: number; }): number; explicitInterface(this: I): number; explicitThis(this: I): number; implicitMethod(this: I): number; implicitFunction: () => any; } +>{ a: 12, explicitVoid2: () => this.a, // ok, this: any because it refers to some outer object (window?) explicitVoid1() { return 12; }, explicitStructural() { return this.a; }, explicitInterface() { return this.a; }, explicitThis() { return this.a; }, implicitMethod() { return this.a; }, implicitFunction: () => this.a, // ok, this: any because it refers to some outer object (window?)} : { a: number; explicitVoid2: () => any; explicitVoid1(): number; explicitStructural(): number; explicitInterface(): number; explicitThis(): number; implicitMethod(): number; implicitFunction: () => any; } a: 12, >a : number @@ -161,7 +161,7 @@ let impl: I = { >12 : number explicitStructural() { ->explicitStructural : (this: { a: number; }) => number +>explicitStructural : () => number return this.a; >this.a : number @@ -170,7 +170,7 @@ let impl: I = { }, explicitInterface() { ->explicitInterface : (this: I) => number +>explicitInterface : () => number return this.a; >this.a : number @@ -179,7 +179,7 @@ let impl: I = { }, explicitThis() { ->explicitThis : (this: I) => number +>explicitThis : () => number return this.a; >this.a : number @@ -188,7 +188,7 @@ let impl: I = { }, implicitMethod() { ->implicitMethod : (this: I) => number +>implicitMethod : () => number return this.a; >this.a : number @@ -220,21 +220,21 @@ impl.explicitVoid2 = () => 12; >12 : number impl.explicitStructural = function() { return this.a; }; ->impl.explicitStructural = function() { return this.a; } : (this: { a: number; }) => number +>impl.explicitStructural = function() { return this.a; } : () => number >impl.explicitStructural : (this: { a: number; }) => number >impl : I >explicitStructural : (this: { a: number; }) => number ->function() { return this.a; } : (this: { a: number; }) => number +>function() { return this.a; } : () => number >this.a : number >this : { a: number; } >a : number impl.explicitInterface = function() { return this.a; }; ->impl.explicitInterface = function() { return this.a; } : (this: I) => number +>impl.explicitInterface = function() { return this.a; } : () => number >impl.explicitInterface : (this: I) => number >impl : I >explicitInterface : (this: I) => number ->function() { return this.a; } : (this: I) => number +>function() { return this.a; } : () => number >this.a : number >this : I >a : number @@ -256,21 +256,21 @@ impl.explicitInterface = () => 12; >12 : number impl.explicitThis = function () { return this.a; }; ->impl.explicitThis = function () { return this.a; } : (this: I) => number +>impl.explicitThis = function () { return this.a; } : () => number >impl.explicitThis : (this: I) => number >impl : I >explicitThis : (this: I) => number ->function () { return this.a; } : (this: I) => number +>function () { return this.a; } : () => number >this.a : number >this : I >a : number impl.implicitMethod = function () { return this.a; }; ->impl.implicitMethod = function () { return this.a; } : (this: I) => number +>impl.implicitMethod = function () { return this.a; } : () => number >impl.implicitMethod : (this: I) => number >impl : I >implicitMethod : (this: I) => number ->function () { return this.a; } : (this: I) => number +>function () { return this.a; } : () => number >this.a : number >this : I >a : number @@ -719,11 +719,11 @@ c.explicitThis = function(this: C, m: number) { return this.n + m }; // this:any compatibility c.explicitC = function(m) { return this.n + m }; ->c.explicitC = function(m) { return this.n + m } : (this: C, m: number) => number +>c.explicitC = function(m) { return this.n + m } : (m: number) => number >c.explicitC : (this: C, m: number) => number >c : C >explicitC : (this: C, m: number) => number ->function(m) { return this.n + m } : (this: C, m: number) => number +>function(m) { return this.n + m } : (m: number) => number >m : number >this.n + m : number >this.n : number @@ -732,11 +732,11 @@ c.explicitC = function(m) { return this.n + m }; >m : number c.explicitProperty = function(m) { return this.n + m }; ->c.explicitProperty = function(m) { return this.n + m } : (this: { n: number; }, m: number) => number +>c.explicitProperty = function(m) { return this.n + m } : (m: number) => number >c.explicitProperty : (this: { n: number; }, m: number) => number >c : C >explicitProperty : (this: { n: number; }, m: number) => number ->function(m) { return this.n + m } : (this: { n: number; }, m: number) => number +>function(m) { return this.n + m } : (m: number) => number >m : number >this.n + m : number >this.n : number @@ -745,11 +745,11 @@ c.explicitProperty = function(m) { return this.n + m }; >m : number c.explicitThis = function(m) { return this.n + m }; ->c.explicitThis = function(m) { return this.n + m } : (this: C, m: number) => number +>c.explicitThis = function(m) { return this.n + m } : (m: number) => number >c.explicitThis : (this: C, m: number) => number >c : C >explicitThis : (this: C, m: number) => number ->function(m) { return this.n + m } : (this: C, m: number) => number +>function(m) { return this.n + m } : (m: number) => number >m : number >this.n + m : number >this.n : number @@ -758,11 +758,11 @@ c.explicitThis = function(m) { return this.n + m }; >m : number c.implicitThis = function(m) { return this.n + m }; ->c.implicitThis = function(m) { return this.n + m } : (this: C, m: number) => number +>c.implicitThis = function(m) { return this.n + m } : (m: number) => number >c.implicitThis : (this: C, m: number) => number >c : C >implicitThis : (this: C, m: number) => number ->function(m) { return this.n + m } : (this: C, m: number) => number +>function(m) { return this.n + m } : (m: number) => number >m : number >this.n + m : number >this.n : number diff --git a/tests/cases/fourslash/quickInfoOnThis.ts b/tests/cases/fourslash/quickInfoOnThis.ts index cef78efe0cc..3213b85174e 100644 --- a/tests/cases/fourslash/quickInfoOnThis.ts +++ b/tests/cases/fourslash/quickInfoOnThis.ts @@ -42,6 +42,17 @@ ////function explicitLiteral(th/*14*/is: { n: number }): void { //// console.log(th/*15*/is); ////} +//// +//// interface ContextualInterface { +//// m: number; +//// method(this: this, n: number); +//// } +//// let o: ContextualInterface = { +//// m: 12, +//// method(n) { +//// let x = this/*16*/.m; +//// } +//// } goTo.marker('1'); verify.quickInfoIs('void'); @@ -73,4 +84,7 @@ goTo.marker('14'); verify.quickInfoIs('(parameter) this: {\n n: number;\n}'); goTo.marker('15'); -verify.quickInfoIs('this: {\n n: number;\n}'); \ No newline at end of file +verify.quickInfoIs('this: {\n n: number;\n}'); + +goTo.marker('16'); +verify.quickInfoIs('this: ContextualInterface'); \ No newline at end of file From c7e80e19f0bf61d9097e89e4dc1864e51b128821 Mon Sep 17 00:00:00 2001 From: vilicvane Date: Sat, 6 Feb 2016 16:51:25 +0800 Subject: [PATCH 040/274] Avoid writing files that are not changed while compiling incrementally. --- src/compiler/sys.ts | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 9c3972b2756..69277f65a92 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -39,6 +39,15 @@ namespace ts { referenceCount: number; } + interface OutputFingerprint { + hash: string; + mtime: Date; + } + + interface OutputFingerprintMap { + [fileName: string]: OutputFingerprint; + } + declare var require: any; declare var module: any; declare var process: any; @@ -226,6 +235,7 @@ namespace ts { const _fs = require("fs"); const _path = require("path"); const _os = require("os"); + const _crypto = require("crypto"); // average async stat takes about 30 microseconds // set chunk size to do 30 files in < 1 millisecond @@ -439,12 +449,26 @@ namespace ts { return buffer.toString("utf8"); } + const outputFingerprintMap: OutputFingerprintMap = {}; + function writeFile(fileName: string, data: string, writeByteOrderMark?: boolean): void { // If a BOM is required, emit one if (writeByteOrderMark) { data = "\uFEFF" + data; } + const md5 = getMd5(data); + const mtimeBefore = _fs.existsSync(fileName) && _fs.statSync(fileName).mtime; + + if (mtimeBefore && outputFingerprintMap.hasOwnProperty(fileName)) { + const fingerprint = outputFingerprintMap[fileName]; + + // If output has not been changed, and the file has no external modification + if (fingerprint.hash === md5 && fingerprint.mtime.getTime() === mtimeBefore.getTime()) { + return; + } + } + let fd: number; try { @@ -456,6 +480,19 @@ namespace ts { _fs.closeSync(fd); } } + + const mtimeAfter = _fs.statSync(fileName).mtime; + + outputFingerprintMap[fileName] = { + hash: md5, + mtime: mtimeAfter + }; + } + + function getMd5(data: string): string { + const hash = _crypto.createHash("md5"); + hash.update(data); + return hash.digest("hex"); } function getCanonicalPath(path: string): string { From fa598758b12d9b06c2b21579e8512a32bffd5065 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 8 Feb 2016 09:41:57 -0800 Subject: [PATCH 041/274] Improve display and contextual typing of `this` 1. Always display `this` type if annotated. 2. Contextually type un-annotated `this` parameters in addition to `this` expressions. --- src/compiler/checker.ts | 9 +- .../reference/contextualTyping24.errors.txt | 4 +- .../looseThisTypeInFunctions.errors.txt | 4 +- .../reference/thisTypeInFunctions.types | 128 +++++++++--------- .../thisTypeInFunctionsNegative.errors.txt | 16 +-- tests/cases/fourslash/quickInfoOnThis.ts | 16 ++- 6 files changed, 92 insertions(+), 85 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index be98dc985b5..06986107fbb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2203,15 +2203,14 @@ namespace ts { function buildDisplayForParametersAndDelimiters(thisType: Type, parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) { writePunctuation(writer, SyntaxKind.OpenParenToken); - const useThisType = thisType && thisType.symbol; - if (useThisType) { + if (thisType) { writeKeyword(writer, SyntaxKind.ThisKeyword); writePunctuation(writer, SyntaxKind.ColonToken); writeSpace(writer); buildTypeDisplay(thisType, writer, enclosingDeclaration, flags, symbolStack); } for (let i = 0; i < parameters.length; i++) { - if (i > 0 || useThisType) { + if (i > 0 || thisType) { writePunctuation(writer, SyntaxKind.CommaToken); writeSpace(writer); } @@ -2690,7 +2689,9 @@ namespace ts { } } // Use contextual parameter type if one is available - const type = getContextuallyTypedParameterType(declaration); + const type = declaration.symbol.name === "this" + ? getContextuallyTypedThisType(func) + : getContextuallyTypedParameterType(declaration); if (type) { return type; } diff --git a/tests/baselines/reference/contextualTyping24.errors.txt b/tests/baselines/reference/contextualTyping24.errors.txt index b4d0d534456..d5cb13e4e3e 100644 --- a/tests/baselines/reference/contextualTyping24.errors.txt +++ b/tests/baselines/reference/contextualTyping24.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/contextualTyping24.ts(1,55): error TS2322: Type '(a: string) => number' is not assignable to type '(a: { (): number; (i: number): number; }) => number'. +tests/cases/compiler/contextualTyping24.ts(1,55): error TS2322: Type '(this: void, a: string) => number' is not assignable to type '(a: { (): number; (i: number): number; }) => number'. Types of parameters 'a' and 'a' are incompatible. Type 'string' is not assignable to type '{ (): number; (i: number): number; }'. @@ -6,6 +6,6 @@ tests/cases/compiler/contextualTyping24.ts(1,55): error TS2322: Type '(a: string ==== tests/cases/compiler/contextualTyping24.ts (1 errors) ==== var foo:(a:{():number; (i:number):number; })=>number; foo = function(this: void, a:string){return 5}; ~~~ -!!! error TS2322: Type '(a: string) => number' is not assignable to type '(a: { (): number; (i: number): number; }) => number'. +!!! error TS2322: Type '(this: void, a: string) => number' is not assignable to type '(a: { (): number; (i: number): number; }) => number'. !!! error TS2322: Types of parameters 'a' and 'a' are incompatible. !!! error TS2322: Type 'string' is not assignable to type '{ (): number; (i: number): number; }'. \ No newline at end of file diff --git a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt index 317446050a8..4eef7d83f78 100644 --- a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt +++ b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(21,1): error TS2322: Type '(this: C, m: number) => number' is not assignable to type '(m: number) => number'. +tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(21,1): error TS2322: Type '(this: C, m: number) => number' is not assignable to type '(this: void, m: number) => number'. Types of parameters 'this' and 'this' are incompatible. Type 'void' is not assignable to type 'C'. tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(32,5): error TS1005: ',' expected. @@ -30,7 +30,7 @@ tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(46,19): error let c = new C(); c.explicitVoid = c.explicitThis; // error, 'void' is missing everything ~~~~~~~~~~~~~~ -!!! error TS2322: Type '(this: C, m: number) => number' is not assignable to type '(m: number) => number'. +!!! error TS2322: Type '(this: C, m: number) => number' is not assignable to type '(this: void, m: number) => number'. !!! error TS2322: Types of parameters 'this' and 'this' are incompatible. !!! error TS2322: Type 'void' is not assignable to type 'C'. let o = { diff --git a/tests/baselines/reference/thisTypeInFunctions.types b/tests/baselines/reference/thisTypeInFunctions.types index e1044bb3d90..2c334b2caed 100644 --- a/tests/baselines/reference/thisTypeInFunctions.types +++ b/tests/baselines/reference/thisTypeInFunctions.types @@ -56,7 +56,7 @@ class C { >m : number } explicitVoid(this: void, m: number): number { ->explicitVoid : (m: number) => number +>explicitVoid : (this: void, m: number) => number >this : void >m : number @@ -83,11 +83,11 @@ interface I { >a : number explicitVoid1(this: void): number; ->explicitVoid1 : () => number +>explicitVoid1 : (this: void) => number >this : void explicitVoid2(this: void): number; ->explicitVoid2 : () => number +>explicitVoid2 : (this: void) => number >this : void explicitStructural(this: {a: number}): number; @@ -108,7 +108,7 @@ interface I { >implicitMethod : (this: this) => number implicitFunction: () => number; ->implicitFunction : () => number +>implicitFunction : (this: void) => number } function explicitStructural(this: { y: number }, x: number): number { >explicitStructural : (this: { y: number; }, x: number) => number @@ -134,7 +134,7 @@ function justThis(this: { y: number }): number { >y : number } function implicitThis(n: number): number { ->implicitThis : (n: number) => number +>implicitThis : (this: void, n: number) => number >n : number return 12; @@ -204,37 +204,37 @@ let impl: I = { >a : any } impl.explicitVoid1 = function () { return 12; }; ->impl.explicitVoid1 = function () { return 12; } : () => number ->impl.explicitVoid1 : () => number +>impl.explicitVoid1 = function () { return 12; } : (this: void) => number +>impl.explicitVoid1 : (this: void) => number >impl : I ->explicitVoid1 : () => number ->function () { return 12; } : () => number +>explicitVoid1 : (this: void) => number +>function () { return 12; } : (this: void) => number >12 : number impl.explicitVoid2 = () => 12; >impl.explicitVoid2 = () => 12 : () => number ->impl.explicitVoid2 : () => number +>impl.explicitVoid2 : (this: void) => number >impl : I ->explicitVoid2 : () => number +>explicitVoid2 : (this: void) => number >() => 12 : () => number >12 : number impl.explicitStructural = function() { return this.a; }; ->impl.explicitStructural = function() { return this.a; } : () => number +>impl.explicitStructural = function() { return this.a; } : (this: void) => number >impl.explicitStructural : (this: { a: number; }) => number >impl : I >explicitStructural : (this: { a: number; }) => number ->function() { return this.a; } : () => number +>function() { return this.a; } : (this: void) => number >this.a : number >this : { a: number; } >a : number impl.explicitInterface = function() { return this.a; }; ->impl.explicitInterface = function() { return this.a; } : () => number +>impl.explicitInterface = function() { return this.a; } : (this: void) => number >impl.explicitInterface : (this: I) => number >impl : I >explicitInterface : (this: I) => number ->function() { return this.a; } : () => number +>function() { return this.a; } : (this: void) => number >this.a : number >this : I >a : number @@ -256,21 +256,21 @@ impl.explicitInterface = () => 12; >12 : number impl.explicitThis = function () { return this.a; }; ->impl.explicitThis = function () { return this.a; } : () => number +>impl.explicitThis = function () { return this.a; } : (this: void) => number >impl.explicitThis : (this: I) => number >impl : I >explicitThis : (this: I) => number ->function () { return this.a; } : () => number +>function () { return this.a; } : (this: void) => number >this.a : number >this : I >a : number impl.implicitMethod = function () { return this.a; }; ->impl.implicitMethod = function () { return this.a; } : () => number +>impl.implicitMethod = function () { return this.a; } : (this: void) => number >impl.implicitMethod : (this: I) => number >impl : I >implicitMethod : (this: I) => number ->function () { return this.a; } : () => number +>function () { return this.a; } : (this: void) => number >this.a : number >this : I >a : number @@ -285,9 +285,9 @@ impl.implicitMethod = () => 12; impl.implicitFunction = () => this.a; // ok, this: any because it refers to some outer object (window?) >impl.implicitFunction = () => this.a : () => any ->impl.implicitFunction : () => number +>impl.implicitFunction : (this: void) => number >impl : I ->implicitFunction : () => number +>implicitFunction : (this: void) => number >() => this.a : () => any >this.a : any >this : any @@ -308,15 +308,15 @@ let ok: {y: number, f: (this: { y: number }, x: number) => number} = { y: 12, f: >explicitStructural : (this: { y: number; }, x: number) => number let implicitAnyOk: {notSpecified: number, f: (x: number) => number} = { notSpecified: 12, f: implicitThis }; ->implicitAnyOk : { notSpecified: number; f: (x: number) => number; } +>implicitAnyOk : { notSpecified: number; f: (this: void, x: number) => number; } >notSpecified : number ->f : (x: number) => number +>f : (this: void, x: number) => number >x : number ->{ notSpecified: 12, f: implicitThis } : { notSpecified: number; f: (n: number) => number; } +>{ notSpecified: 12, f: implicitThis } : { notSpecified: number; f: (this: void, n: number) => number; } >notSpecified : number >12 : number ->f : (n: number) => number ->implicitThis : (n: number) => number +>f : (this: void, n: number) => number +>implicitThis : (this: void, n: number) => number ok.f(13); >ok.f(13) : number @@ -327,14 +327,14 @@ ok.f(13); implicitThis(12); >implicitThis(12) : number ->implicitThis : (n: number) => number +>implicitThis : (this: void, n: number) => number >12 : number implicitAnyOk.f(12); >implicitAnyOk.f(12) : number ->implicitAnyOk.f : (x: number) => number ->implicitAnyOk : { notSpecified: number; f: (x: number) => number; } ->f : (x: number) => number +>implicitAnyOk.f : (this: void, x: number) => number +>implicitAnyOk : { notSpecified: number; f: (this: void, x: number) => number; } +>f : (this: void, x: number) => number >12 : number let c = new C(); @@ -410,7 +410,7 @@ d.implicitThis(12); >12 : number let reconstructed: { ->reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(m: number): number; } +>reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(this: void, m: number): number; } n: number, >n : number @@ -438,12 +438,12 @@ let reconstructed: { >m : number explicitVoid(this: void, m: number): number, ->explicitVoid : (m: number) => number +>explicitVoid : (this: void, m: number) => number >this : void >m : number } = { ->{ n: 12, explicitThis: c.explicitThis, implicitThis: c.implicitThis, explicitC: c.explicitC, explicitProperty: c.explicitProperty, explicitVoid: c.explicitVoid} : { n: number; explicitThis: (this: C, m: number) => number; implicitThis: (this: C, m: number) => number; explicitC: (this: C, m: number) => number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid: (m: number) => number; } +>{ n: 12, explicitThis: c.explicitThis, implicitThis: c.implicitThis, explicitC: c.explicitC, explicitProperty: c.explicitProperty, explicitVoid: c.explicitVoid} : { n: number; explicitThis: (this: C, m: number) => number; implicitThis: (this: C, m: number) => number; explicitC: (this: C, m: number) => number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid: (this: void, m: number) => number; } n: 12, >n : number @@ -474,23 +474,23 @@ let reconstructed: { >explicitProperty : (this: { n: number; }, m: number) => number explicitVoid: c.explicitVoid ->explicitVoid : (m: number) => number ->c.explicitVoid : (m: number) => number +>explicitVoid : (this: void, m: number) => number +>c.explicitVoid : (this: void, m: number) => number >c : C ->explicitVoid : (m: number) => number +>explicitVoid : (this: void, m: number) => number }; reconstructed.explicitProperty(11); >reconstructed.explicitProperty(11) : number >reconstructed.explicitProperty : (this: { n: number; }, m: number) => number ->reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(m: number): number; } +>reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(this: void, m: number): number; } >explicitProperty : (this: { n: number; }, m: number) => number >11 : number reconstructed.implicitThis(11); >reconstructed.implicitThis(11) : number >reconstructed.implicitThis : (m: number) => number ->reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(m: number): number; } +>reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(this: void, m: number): number; } >implicitThis : (m: number) => number >11 : number @@ -520,14 +520,14 @@ let anyToSpecified: (this: { y: number }, x: number) => number = function(x: num >this : { y: number; } >y : number >x : number ->function(x: number): number { return x + 12; } : (x: number) => number +>function(x: number): number { return x + 12; } : (this: void, x: number) => number >x : number >x + 12 : number >x : number >12 : number let unspecifiedLambda: (x: number) => number = x => x + 12; ->unspecifiedLambda : (x: number) => number +>unspecifiedLambda : (this: void, x: number) => number >x : number >x => x + 12 : (x: number) => number >x : number @@ -536,7 +536,7 @@ let unspecifiedLambda: (x: number) => number = x => x + 12; >12 : number let specifiedLambda: (this: void, x: number) => number = x => x + 12; ->specifiedLambda : (x: number) => number +>specifiedLambda : (this: void, x: number) => number >this : void >x : number >x => x + 12 : (x: number) => number @@ -550,14 +550,14 @@ let unspecifiedLambdaToSpecified: (this: {y: number}, x: number) => number = uns >this : { y: number; } >y : number >x : number ->unspecifiedLambda : (x: number) => number +>unspecifiedLambda : (this: void, x: number) => number let specifiedLambdaToSpecified: (this: {y: number}, x: number) => number = specifiedLambda; >specifiedLambdaToSpecified : (this: { y: number; }, x: number) => number >this : { y: number; } >y : number >x : number ->specifiedLambda : (x: number) => number +>specifiedLambda : (this: void, x: number) => number let explicitCFunction: (this: C, m: number) => number; @@ -622,7 +622,7 @@ c.explicitProperty = reconstructed.explicitProperty; >c : C >explicitProperty : (this: { n: number; }, m: number) => number >reconstructed.explicitProperty : (this: { n: number; }, m: number) => number ->reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(m: number): number; } +>reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(this: void, m: number): number; } >explicitProperty : (this: { n: number; }, m: number) => number // lambdas are assignable to anything @@ -719,11 +719,11 @@ c.explicitThis = function(this: C, m: number) { return this.n + m }; // this:any compatibility c.explicitC = function(m) { return this.n + m }; ->c.explicitC = function(m) { return this.n + m } : (m: number) => number +>c.explicitC = function(m) { return this.n + m } : (this: void, m: number) => number >c.explicitC : (this: C, m: number) => number >c : C >explicitC : (this: C, m: number) => number ->function(m) { return this.n + m } : (m: number) => number +>function(m) { return this.n + m } : (this: void, m: number) => number >m : number >this.n + m : number >this.n : number @@ -732,11 +732,11 @@ c.explicitC = function(m) { return this.n + m }; >m : number c.explicitProperty = function(m) { return this.n + m }; ->c.explicitProperty = function(m) { return this.n + m } : (m: number) => number +>c.explicitProperty = function(m) { return this.n + m } : (this: void, m: number) => number >c.explicitProperty : (this: { n: number; }, m: number) => number >c : C >explicitProperty : (this: { n: number; }, m: number) => number ->function(m) { return this.n + m } : (m: number) => number +>function(m) { return this.n + m } : (this: void, m: number) => number >m : number >this.n + m : number >this.n : number @@ -745,11 +745,11 @@ c.explicitProperty = function(m) { return this.n + m }; >m : number c.explicitThis = function(m) { return this.n + m }; ->c.explicitThis = function(m) { return this.n + m } : (m: number) => number +>c.explicitThis = function(m) { return this.n + m } : (this: void, m: number) => number >c.explicitThis : (this: C, m: number) => number >c : C >explicitThis : (this: C, m: number) => number ->function(m) { return this.n + m } : (m: number) => number +>function(m) { return this.n + m } : (this: void, m: number) => number >m : number >this.n + m : number >this.n : number @@ -758,11 +758,11 @@ c.explicitThis = function(m) { return this.n + m }; >m : number c.implicitThis = function(m) { return this.n + m }; ->c.implicitThis = function(m) { return this.n + m } : (m: number) => number +>c.implicitThis = function(m) { return this.n + m } : (this: void, m: number) => number >c.implicitThis : (this: C, m: number) => number >c : C >implicitThis : (this: C, m: number) => number ->function(m) { return this.n + m } : (m: number) => number +>function(m) { return this.n + m } : (this: void, m: number) => number >m : number >this.n + m : number >this.n : number @@ -776,7 +776,7 @@ c.implicitThis = reconstructed.implicitThis; >c : C >implicitThis : (this: C, m: number) => number >reconstructed.implicitThis : (m: number) => number ->reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(m: number): number; } +>reconstructed : { n: number; explicitThis(this: C, m: number): number; implicitThis(m: number): number; explicitC(this: C, m: number): number; explicitProperty: (this: { n: number; }, m: number) => number; explicitVoid(this: void, m: number): number; } >implicitThis : (m: number) => number c.explicitC = function(this: B, m: number) { return this.n + m }; @@ -797,9 +797,9 @@ c.explicitC = function(this: B, m: number) { return this.n + m }; // this:void compatibility c.explicitVoid = n => n; >c.explicitVoid = n => n : (n: number) => number ->c.explicitVoid : (m: number) => number +>c.explicitVoid : (this: void, m: number) => number >c : C ->explicitVoid : (m: number) => number +>explicitVoid : (this: void, m: number) => number >n => n : (n: number) => number >n : number >n : number @@ -978,7 +978,7 @@ function LiteralTypeThis(this: {x: string}) { >"ok" : string } function AnyThis(this: any) { ->AnyThis : () => void +>AnyThis : (this: any) => void >this : any this.x = "ok"; @@ -1001,20 +1001,20 @@ let literalTypeThis = new LiteralTypeThis(); let anyThis = new AnyThis(); >anyThis : any >new AnyThis() : any ->AnyThis : () => void +>AnyThis : (this: any) => void //// type parameter inference //// declare var f: { ->f : { (x: number): number; call(this: (...argArray: any[]) => U, ...argArray: any[]): U; } +>f : { (this: void, x: number): number; call(this: (this: void, ...argArray: any[]) => U, ...argArray: any[]): U; } (this: void, x: number): number, >this : void >x : number call(this: (...argArray: any[]) => U, ...argArray: any[]): U; ->call : (this: (...argArray: any[]) => U, ...argArray: any[]) => U +>call : (this: (this: void, ...argArray: any[]) => U, ...argArray: any[]) => U >U : U ->this : (...argArray: any[]) => U +>this : (this: void, ...argArray: any[]) => U >argArray : any[] >U : U >argArray : any[] @@ -1024,13 +1024,13 @@ declare var f: { let n: number = f.call(12); >n : number >f.call(12) : number ->f.call : (this: (...argArray: any[]) => U, ...argArray: any[]) => U ->f : { (x: number): number; call(this: (...argArray: any[]) => U, ...argArray: any[]): U; } ->call : (this: (...argArray: any[]) => U, ...argArray: any[]) => U +>f.call : (this: (this: void, ...argArray: any[]) => U, ...argArray: any[]) => U +>f : { (this: void, x: number): number; call(this: (this: void, ...argArray: any[]) => U, ...argArray: any[]): U; } +>call : (this: (this: void, ...argArray: any[]) => U, ...argArray: any[]) => U >12 : number function missingTypeIsImplicitAny(this, a: number) { return a; } ->missingTypeIsImplicitAny : (a: number) => number +>missingTypeIsImplicitAny : (this: any, a: number) => number >this : any >a : number >a : number diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt index 0b755b9e0bd..fdb9489f639 100644 --- a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt @@ -33,7 +33,7 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(95,1): err tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(96,1): error TS2346: Supplied parameters do not match any signature of call target. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(97,20): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(98,1): error TS2346: Supplied parameters do not match any signature of call target. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(101,5): error TS2322: Type '(this: { y: number; }, x: number) => number' is not assignable to type '(x: number) => number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(101,5): error TS2322: Type '(this: { y: number; }, x: number) => number' is not assignable to type '(this: void, x: number) => number'. Types of parameters 'this' and 'this' are incompatible. Type 'void' is not assignable to type '{ y: number; }'. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(124,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. @@ -70,13 +70,13 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(134,1): er Types of parameters 'this' and 'this' are incompatible. Type '{ n: number; }' is not assignable to type 'D'. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(135,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(136,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(m: number) => number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(136,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: void, m: number) => number'. Types of parameters 'this' and 'this' are incompatible. Type 'void' is not assignable to type 'D'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(137,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(m: number) => number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(137,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: void, m: number) => number'. Types of parameters 'this' and 'this' are incompatible. Type 'void' is not assignable to type 'D'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(138,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(m: number) => number'. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(138,1): error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: void, m: number) => number'. Types of parameters 'this' and 'this' are incompatible. Type 'void' is not assignable to type 'D'. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(146,51): error TS2339: Property 'x' does not exist on type 'typeof Base1'. @@ -287,7 +287,7 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,35): e // oops, this triggers contextual typing, which needs to be updated to understand that =>'s `this` is void. let specifiedToImplicitVoid: (x: number) => number = explicitStructural; ~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2322: Type '(this: { y: number; }, x: number) => number' is not assignable to type '(x: number) => number'. +!!! error TS2322: Type '(this: { y: number; }, x: number) => number' is not assignable to type '(this: void, x: number) => number'. !!! error TS2322: Types of parameters 'this' and 'this' are incompatible. !!! error TS2322: Type 'void' is not assignable to type '{ y: number; }'. @@ -371,17 +371,17 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,35): e !!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: C, m: number) => number'. c.explicitVoid = d.implicitD; ~~~~~~~~~~~~~~ -!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(m: number) => number'. +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: void, m: number) => number'. !!! error TS2322: Types of parameters 'this' and 'this' are incompatible. !!! error TS2322: Type 'void' is not assignable to type 'D'. c.explicitVoid = d.explicitD; ~~~~~~~~~~~~~~ -!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(m: number) => number'. +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: void, m: number) => number'. !!! error TS2322: Types of parameters 'this' and 'this' are incompatible. !!! error TS2322: Type 'void' is not assignable to type 'D'. c.explicitVoid = d.explicitThis; ~~~~~~~~~~~~~~ -!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(m: number) => number'. +!!! error TS2322: Type '(this: D, m: number) => number' is not assignable to type '(this: void, m: number) => number'. !!! error TS2322: Types of parameters 'this' and 'this' are incompatible. !!! error TS2322: Type 'void' is not assignable to type 'D'. diff --git a/tests/cases/fourslash/quickInfoOnThis.ts b/tests/cases/fourslash/quickInfoOnThis.ts index 3213b85174e..57bbb6c5a3e 100644 --- a/tests/cases/fourslash/quickInfoOnThis.ts +++ b/tests/cases/fourslash/quickInfoOnThis.ts @@ -43,16 +43,20 @@ //// console.log(th/*15*/is); ////} //// -//// interface ContextualInterface { +////interface ContextualInterface { //// m: number; //// method(this: this, n: number); -//// } -//// let o: ContextualInterface = { +////} +////let o: ContextualInterface = { //// m: 12, //// method(n) { //// let x = this/*16*/.m; //// } -//// } +////} +////interface ContextualInterface2 { +//// (this: void, n: number): void; +////} +////let contextualInterface2: ContextualInterface2 = function (th/*17*/is, n) { } goTo.marker('1'); verify.quickInfoIs('void'); @@ -87,4 +91,6 @@ goTo.marker('15'); verify.quickInfoIs('this: {\n n: number;\n}'); goTo.marker('16'); -verify.quickInfoIs('this: ContextualInterface'); \ No newline at end of file +verify.quickInfoIs('this: ContextualInterface'); +goTo.marker('17'); +verify.quickInfoIs('(parameter) this: void'); \ No newline at end of file From 738713b146d055194254640d8b079cc54ca6cd7f Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 8 Feb 2016 14:01:51 -0800 Subject: [PATCH 042/274] Improve error reporting 1. Fix bug in error reporting in compareSignaturesRelated. 2. When the this-argument is a union type, allow assignability when the method's signature is assignable to *any* member of the union. --- src/compiler/checker.ts | 12 +- src/compiler/core.ts | 17 + .../reference/thisTypeInFunctions.js | 24 +- .../reference/thisTypeInFunctions.symbols | 382 +++++++++--------- .../reference/thisTypeInFunctions.types | 25 +- .../types/thisType/thisTypeInFunctions.ts | 11 +- 6 files changed, 267 insertions(+), 204 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 06986107fbb..0acb3a127d5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5305,7 +5305,9 @@ namespace ts { if (!related) { related = compareTypes(source.thisType, target.thisType, /*reportErrors*/ false); if (!related) { - errorReporter(Diagnostics.Types_of_parameters_0_and_1_are_incompatible, "this", "this"); + if (reportErrors) { + errorReporter(Diagnostics.Types_of_parameters_0_and_1_are_incompatible, "this", "this"); + } return Ternary.False; } } @@ -9511,7 +9513,13 @@ namespace ts { const thisArgumentNode = getThisArgumentOfCall(node); const thisArgumentType = thisArgumentNode ? checkExpression(thisArgumentNode) : voidType; const errorNode = reportErrors ? (thisArgumentNode || node) : undefined; - if (!checkTypeRelatedTo(thisArgumentType, signature.thisType, relation, errorNode, headMessage)) { + if (thisArgumentType.flags & TypeFlags.UnionOrIntersection) { + const u = thisArgumentType; + if (!forEach(u.types, t => checkTypeRelatedTo(t, signature.thisType, relation, errorNode, headMessage))) { + return false; + } + } + else if (!checkTypeRelatedTo(thisArgumentType, signature.thisType, relation, errorNode, headMessage)) { return false; } } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 21536da36ff..f1f9d93c5d2 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -91,6 +91,23 @@ namespace ts { return undefined; } + /** + * Iterates through `array` by index and performs the callback on each element of array until the callback + * returns a falsey value, then returns false. + * If no such value is found, the callback is applied to each element of array and `true` is returned. + */ + export function trueForAll(array: T[], callback: (element: T, index: number) => boolean): boolean { + if (array) { + for (let i = 0, len = array.length; i < len; i++) { + if (!callback(array[i], i)) { + return false; + } + } + } + + return true; + } + export function contains(array: T[], value: T): boolean { if (array) { for (const v of array) { diff --git a/tests/baselines/reference/thisTypeInFunctions.js b/tests/baselines/reference/thisTypeInFunctions.js index f3ad84acb55..af55603a4b7 100644 --- a/tests/baselines/reference/thisTypeInFunctions.js +++ b/tests/baselines/reference/thisTypeInFunctions.js @@ -1,5 +1,8 @@ //// [thisTypeInFunctions.ts] // body checking +class B { + n: number; +} class C { n: number; explicitThis(this: this, m: number): number { @@ -19,9 +22,6 @@ class C { } } class D extends C { } -class B { - n: number; -} interface I { a: number; explicitVoid1(this: void): number; @@ -185,6 +185,11 @@ d2.implicit = d1.explicit // ok, 'y' in { x, y } (c assignable to f) b1.implicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) +// union assignability + +let b1b2: Base1 | Base2; +b1b2.implicit(); + ////// use this-type for construction with new //// function InterfaceThis(this: I) { this.a = 12; @@ -216,6 +221,11 @@ var __extends = (this && this.__extends) || function (d, b) { }; var _this = this; // body checking +var B = (function () { + function B() { + } + return B; +}()); var C = (function () { function C() { } @@ -243,11 +253,6 @@ var D = (function (_super) { } return D; }(C)); -var B = (function () { - function B() { - } - return B; -}()); function explicitStructural(x) { return x + this.y; } @@ -390,6 +395,9 @@ d1.implicit = b2.implicit; // ok, 'y' in D: { x, y } (d assignable e) d2.implicit = d1.explicit; // ok, 'y' in { x, y } (c assignable to f) b1.implicit = d2.implicit; // ok, 'x' and 'y' not in C: { x } (c assignable to f) b1.explicit = d2.implicit; // ok, 'x' and 'y' not in C: { x } (c assignable to f) +// union assignability +var b1b2; +b1b2.implicit(); ////// use this-type for construction with new //// function InterfaceThis() { this.a = 12; diff --git a/tests/baselines/reference/thisTypeInFunctions.symbols b/tests/baselines/reference/thisTypeInFunctions.symbols index bb6a9acfdd0..120494c206f 100644 --- a/tests/baselines/reference/thisTypeInFunctions.symbols +++ b/tests/baselines/reference/thisTypeInFunctions.symbols @@ -1,77 +1,77 @@ === tests/cases/conformance/types/thisType/thisTypeInFunctions.ts === // body checking -class C { ->C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +class B { +>B : Symbol(B, Decl(thisTypeInFunctions.ts, 0, 0)) n: number; >n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) +} +class C { +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) + + n: number; +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 4, 9)) explicitThis(this: this, m: number): number { ->explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 3, 17)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 3, 28)) +>explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 6, 17)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 6, 28)) return this.n + m; ->this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) ->this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 3, 28)) +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 4, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 4, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 6, 28)) } implicitThis(m: number): number { ->implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 6, 17)) +>implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 9, 17)) return this.n + m; ->this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) ->this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 6, 17)) +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 4, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 4, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 9, 17)) } explicitC(this: C, m: number): number { ->explicitC : Symbol(explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 9, 14)) ->C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 9, 22)) +>explicitC : Symbol(explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 12, 14)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 12, 22)) return this.n + m; ->this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) ->this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 1, 9)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 9, 22)) +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 4, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 4, 9)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 12, 22)) } explicitProperty(this: {n: number}, m: number): number { ->explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 12, 21)) ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 12, 39)) +>explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 15, 21)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 15, 28)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 15, 39)) return this.n + m; ->this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) ->this : Symbol(, Decl(thisTypeInFunctions.ts, 12, 26)) ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 12, 39)) +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 15, 28)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 15, 26)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 15, 28)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 15, 39)) } explicitVoid(this: void, m: number): number { ->explicitVoid : Symbol(explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 15, 17)) ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 15, 28)) +>explicitVoid : Symbol(explicitVoid, Decl(thisTypeInFunctions.ts, 17, 5)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 18, 17)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 18, 28)) return m + 1; ->m : Symbol(m, Decl(thisTypeInFunctions.ts, 15, 28)) +>m : Symbol(m, Decl(thisTypeInFunctions.ts, 18, 28)) } } class D extends C { } ->D : Symbol(D, Decl(thisTypeInFunctions.ts, 18, 1)) ->C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>D : Symbol(D, Decl(thisTypeInFunctions.ts, 21, 1)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) -class B { ->B : Symbol(B, Decl(thisTypeInFunctions.ts, 19, 21)) - - n: number; ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 20, 9)) -} interface I { ->I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) a: number; >a : Symbol(a, Decl(thisTypeInFunctions.ts, 23, 13)) @@ -92,7 +92,7 @@ interface I { explicitInterface(this: I): number; >explicitInterface : Symbol(explicitInterface, Decl(thisTypeInFunctions.ts, 27, 50)) >this : Symbol(this, Decl(thisTypeInFunctions.ts, 28, 22)) ->I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) explicitThis(this: this): number; >explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 28, 39)) @@ -134,7 +134,7 @@ function implicitThis(n: number): number { } let impl: I = { >impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) ->I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) a: 12, >a : Symbol(a, Decl(thisTypeInFunctions.ts, 42, 15)) @@ -159,7 +159,7 @@ let impl: I = { return this.a; >this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) ->this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) >a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) }, @@ -168,7 +168,7 @@ let impl: I = { return this.a; >this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) ->this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) >a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) }, @@ -177,7 +177,7 @@ let impl: I = { return this.a; >this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) ->this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) >a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) }, @@ -207,7 +207,7 @@ impl.explicitInterface = function() { return this.a; }; >impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) >explicitInterface : Symbol(I.explicitInterface, Decl(thisTypeInFunctions.ts, 27, 50)) >this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) ->this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) >a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) impl.explicitStructural = () => 12; @@ -225,7 +225,7 @@ impl.explicitThis = function () { return this.a; }; >impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) >explicitThis : Symbol(I.explicitThis, Decl(thisTypeInFunctions.ts, 28, 39)) >this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) ->this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) >a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) impl.implicitMethod = function () { return this.a; }; @@ -233,7 +233,7 @@ impl.implicitMethod = function () { return this.a; }; >impl : Symbol(impl, Decl(thisTypeInFunctions.ts, 42, 3)) >implicitMethod : Symbol(I.implicitMethod, Decl(thisTypeInFunctions.ts, 29, 37)) >this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) ->this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) >a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) impl.implicitMethod = () => 12; @@ -282,57 +282,57 @@ implicitAnyOk.f(12); let c = new C(); >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) let d = new D(); >d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) ->D : Symbol(D, Decl(thisTypeInFunctions.ts, 18, 1)) +>D : Symbol(D, Decl(thisTypeInFunctions.ts, 21, 1)) let ripped = c.explicitC; >ripped : Symbol(ripped, Decl(thisTypeInFunctions.ts, 79, 3)) ->c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) c.explicitC(12); ->c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) c.explicitProperty(12); ->c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) c.explicitThis(12); ->c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) c.implicitThis(12); ->c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) d.explicitC(12); ->d.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>d.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) d.explicitProperty(12); ->d.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>d.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) ->explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) d.explicitThis(12); ->d.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>d.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) >d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) ->explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) d.implicitThis(12); ->d.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>d.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) >d : Symbol(d, Decl(thisTypeInFunctions.ts, 78, 3)) ->implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) let reconstructed: { >reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 88, 3)) @@ -343,7 +343,7 @@ let reconstructed: { explicitThis(this: C, m: number): number, // note: this: this is not allowed in an object literal type. >explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 89, 14)) >this : Symbol(this, Decl(thisTypeInFunctions.ts, 90, 17)) ->C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 90, 25)) implicitThis(m: number): number, @@ -353,7 +353,7 @@ let reconstructed: { explicitC(this: C, m: number): number, >explicitC : Symbol(explicitC, Decl(thisTypeInFunctions.ts, 91, 36)) >this : Symbol(this, Decl(thisTypeInFunctions.ts, 92, 14)) ->C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 92, 22)) explicitProperty: (this: {n : number}, m: number) => number, @@ -373,33 +373,33 @@ let reconstructed: { explicitThis: c.explicitThis, >explicitThis : Symbol(explicitThis, Decl(thisTypeInFunctions.ts, 96, 10)) ->c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) implicitThis: c.implicitThis, >implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 97, 33)) ->c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) explicitC: c.explicitC, >explicitC : Symbol(explicitC, Decl(thisTypeInFunctions.ts, 98, 33)) ->c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) explicitProperty: c.explicitProperty, >explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 99, 27)) ->c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) explicitVoid: c.explicitVoid >explicitVoid : Symbol(explicitVoid, Decl(thisTypeInFunctions.ts, 100, 41)) ->c.explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) +>c.explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 17, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) +>explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 17, 5)) }; reconstructed.explicitProperty(11); @@ -467,7 +467,7 @@ let specifiedLambdaToSpecified: (this: {y: number}, x: number) => number = speci let explicitCFunction: (this: C, m: number) => number; >explicitCFunction : Symbol(explicitCFunction, Decl(thisTypeInFunctions.ts, 117, 3)) >this : Symbol(this, Decl(thisTypeInFunctions.ts, 117, 24)) ->C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 117, 32)) let explicitPropertyFunction: (this: {n: number}, m: number) => number; @@ -477,33 +477,33 @@ let explicitPropertyFunction: (this: {n: number}, m: number) => number; >m : Symbol(m, Decl(thisTypeInFunctions.ts, 118, 49)) c.explicitC = explicitCFunction; ->c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >explicitCFunction : Symbol(explicitCFunction, Decl(thisTypeInFunctions.ts, 117, 3)) c.explicitC = function(this: C, m: number) { return this.n + m }; ->c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >this : Symbol(this, Decl(thisTypeInFunctions.ts, 120, 23)) ->C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 120, 31)) ->this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) ->this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) ->n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) +>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 120, 31)) c.explicitProperty = explicitPropertyFunction; ->c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >explicitPropertyFunction : Symbol(explicitPropertyFunction, Decl(thisTypeInFunctions.ts, 118, 3)) c.explicitProperty = function(this: {n: number}, m: number) { return this.n + m }; ->c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >this : Symbol(this, Decl(thisTypeInFunctions.ts, 122, 30)) >n : Symbol(n, Decl(thisTypeInFunctions.ts, 122, 37)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 122, 48)) @@ -513,143 +513,143 @@ c.explicitProperty = function(this: {n: number}, m: number) { return this.n + m >m : Symbol(m, Decl(thisTypeInFunctions.ts, 122, 48)) c.explicitProperty = reconstructed.explicitProperty; ->c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >reconstructed.explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 92, 42)) >reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 88, 3)) >explicitProperty : Symbol(explicitProperty, Decl(thisTypeInFunctions.ts, 92, 42)) // lambdas are assignable to anything c.explicitC = m => m; ->c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 126, 13)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 126, 13)) c.explicitThis = m => m; ->c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 127, 16)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 127, 16)) c.explicitProperty = m => m; ->c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 128, 20)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 128, 20)) // this inside lambdas refer to outer scope // the outer-scoped lambda at top-level is still just `any` c.explicitC = m => m + this.n; ->c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 132, 13)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 132, 13)) c.explicitThis = m => m + this.n; ->c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 133, 16)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 133, 16)) c.explicitProperty = m => m + this.n; ->c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 134, 20)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 134, 20)) //NOTE: this=C here, I guess? c.explicitThis = explicitCFunction; ->c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) >explicitCFunction : Symbol(explicitCFunction, Decl(thisTypeInFunctions.ts, 117, 3)) c.explicitThis = function(this: C, m: number) { return this.n + m }; ->c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) >this : Symbol(this, Decl(thisTypeInFunctions.ts, 138, 26)) ->C : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) +>C : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 138, 34)) ->this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) ->this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) ->n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) +>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 138, 34)) // this:any compatibility c.explicitC = function(m) { return this.n + m }; ->c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 141, 23)) ->this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) ->this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) ->n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) +>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 141, 23)) c.explicitProperty = function(m) { return this.n + m }; ->c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>c.explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 11, 5)) +>explicitProperty : Symbol(C.explicitProperty, Decl(thisTypeInFunctions.ts, 14, 5)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 142, 30)) ->this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) ->this : Symbol(, Decl(thisTypeInFunctions.ts, 12, 26)) ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 12, 28)) +>this.n : Symbol(n, Decl(thisTypeInFunctions.ts, 15, 28)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 15, 26)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 15, 28)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 142, 30)) c.explicitThis = function(m) { return this.n + m }; ->c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>c.explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 2, 14)) +>explicitThis : Symbol(C.explicitThis, Decl(thisTypeInFunctions.ts, 5, 14)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 143, 26)) ->this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) ->this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) ->n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) +>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 143, 26)) c.implicitThis = function(m) { return this.n + m }; ->c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 144, 26)) ->this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) ->this : Symbol(C, Decl(thisTypeInFunctions.ts, 0, 0)) ->n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this.n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) +>this : Symbol(C, Decl(thisTypeInFunctions.ts, 3, 1)) +>n : Symbol(C.n, Decl(thisTypeInFunctions.ts, 4, 9)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 144, 26)) c.implicitThis = reconstructed.implicitThis; ->c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>c.implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 5, 5)) +>implicitThis : Symbol(C.implicitThis, Decl(thisTypeInFunctions.ts, 8, 5)) >reconstructed.implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 90, 45)) >reconstructed : Symbol(reconstructed, Decl(thisTypeInFunctions.ts, 88, 3)) >implicitThis : Symbol(implicitThis, Decl(thisTypeInFunctions.ts, 90, 45)) c.explicitC = function(this: B, m: number) { return this.n + m }; ->c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>c.explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 8, 5)) +>explicitC : Symbol(C.explicitC, Decl(thisTypeInFunctions.ts, 11, 5)) >this : Symbol(this, Decl(thisTypeInFunctions.ts, 147, 23)) ->B : Symbol(B, Decl(thisTypeInFunctions.ts, 19, 21)) +>B : Symbol(B, Decl(thisTypeInFunctions.ts, 0, 0)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 147, 31)) ->this.n : Symbol(B.n, Decl(thisTypeInFunctions.ts, 20, 9)) ->this : Symbol(B, Decl(thisTypeInFunctions.ts, 19, 21)) ->n : Symbol(B.n, Decl(thisTypeInFunctions.ts, 20, 9)) +>this.n : Symbol(B.n, Decl(thisTypeInFunctions.ts, 1, 9)) +>this : Symbol(B, Decl(thisTypeInFunctions.ts, 0, 0)) +>n : Symbol(B.n, Decl(thisTypeInFunctions.ts, 1, 9)) >m : Symbol(m, Decl(thisTypeInFunctions.ts, 147, 31)) // this:void compatibility c.explicitVoid = n => n; ->c.explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) +>c.explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 17, 5)) >c : Symbol(c, Decl(thisTypeInFunctions.ts, 77, 3)) ->explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 14, 5)) +>explicitVoid : Symbol(C.explicitVoid, Decl(thisTypeInFunctions.ts, 17, 5)) >n : Symbol(n, Decl(thisTypeInFunctions.ts, 150, 16)) >n : Symbol(n, Decl(thisTypeInFunctions.ts, 150, 16)) @@ -791,72 +791,84 @@ b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) >d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 176, 3)) >implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) +// union assignability + +let b1b2: Base1 | Base2; +>b1b2 : Symbol(b1b2, Decl(thisTypeInFunctions.ts, 188, 3)) +>Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) +>Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 164, 1)) + +b1b2.implicit(); +>b1b2.implicit : Symbol(implicit, Decl(thisTypeInFunctions.ts, 154, 14), Decl(thisTypeInFunctions.ts, 166, 13)) +>b1b2 : Symbol(b1b2, Decl(thisTypeInFunctions.ts, 188, 3)) +>implicit : Symbol(implicit, Decl(thisTypeInFunctions.ts, 154, 14), Decl(thisTypeInFunctions.ts, 166, 13)) + ////// use this-type for construction with new //// function InterfaceThis(this: I) { ->InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 184, 25)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 187, 23)) ->I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 189, 16)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 192, 23)) +>I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) this.a = 12; >this.a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) ->this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 1)) +>this : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) >a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) } function LiteralTypeThis(this: {x: string}) { ->LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 189, 1)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 190, 25)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 190, 32)) +>LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 194, 1)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 195, 25)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 195, 32)) this.x = "ok"; ->this.x : Symbol(x, Decl(thisTypeInFunctions.ts, 190, 32)) ->this : Symbol(, Decl(thisTypeInFunctions.ts, 190, 30)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 190, 32)) +>this.x : Symbol(x, Decl(thisTypeInFunctions.ts, 195, 32)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 195, 30)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 195, 32)) } function AnyThis(this: any) { ->AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 192, 1)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 193, 17)) +>AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 197, 1)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 198, 17)) this.x = "ok"; } let interfaceThis = new InterfaceThis(); ->interfaceThis : Symbol(interfaceThis, Decl(thisTypeInFunctions.ts, 196, 3)) ->InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 184, 25)) +>interfaceThis : Symbol(interfaceThis, Decl(thisTypeInFunctions.ts, 201, 3)) +>InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 189, 16)) let literalTypeThis = new LiteralTypeThis(); ->literalTypeThis : Symbol(literalTypeThis, Decl(thisTypeInFunctions.ts, 197, 3)) ->LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 189, 1)) +>literalTypeThis : Symbol(literalTypeThis, Decl(thisTypeInFunctions.ts, 202, 3)) +>LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 194, 1)) let anyThis = new AnyThis(); ->anyThis : Symbol(anyThis, Decl(thisTypeInFunctions.ts, 198, 3)) ->AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 192, 1)) +>anyThis : Symbol(anyThis, Decl(thisTypeInFunctions.ts, 203, 3)) +>AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 197, 1)) //// type parameter inference //// declare var f: { ->f : Symbol(f, Decl(thisTypeInFunctions.ts, 201, 11)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 206, 11)) (this: void, x: number): number, ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 202, 5)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 202, 16)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 207, 5)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 207, 16)) call(this: (...argArray: any[]) => U, ...argArray: any[]): U; ->call : Symbol(call, Decl(thisTypeInFunctions.ts, 202, 36)) ->U : Symbol(U, Decl(thisTypeInFunctions.ts, 203, 9)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 203, 12)) ->argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 203, 19)) ->U : Symbol(U, Decl(thisTypeInFunctions.ts, 203, 9)) ->argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 203, 44)) ->U : Symbol(U, Decl(thisTypeInFunctions.ts, 203, 9)) +>call : Symbol(call, Decl(thisTypeInFunctions.ts, 207, 36)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 208, 9)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 208, 12)) +>argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 208, 19)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 208, 9)) +>argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 208, 44)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 208, 9)) }; let n: number = f.call(12); ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 205, 3)) ->f.call : Symbol(call, Decl(thisTypeInFunctions.ts, 202, 36)) ->f : Symbol(f, Decl(thisTypeInFunctions.ts, 201, 11)) ->call : Symbol(call, Decl(thisTypeInFunctions.ts, 202, 36)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 210, 3)) +>f.call : Symbol(call, Decl(thisTypeInFunctions.ts, 207, 36)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 206, 11)) +>call : Symbol(call, Decl(thisTypeInFunctions.ts, 207, 36)) function missingTypeIsImplicitAny(this, a: number) { return a; } ->missingTypeIsImplicitAny : Symbol(missingTypeIsImplicitAny, Decl(thisTypeInFunctions.ts, 205, 27)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 207, 34)) ->a : Symbol(a, Decl(thisTypeInFunctions.ts, 207, 39)) ->a : Symbol(a, Decl(thisTypeInFunctions.ts, 207, 39)) +>missingTypeIsImplicitAny : Symbol(missingTypeIsImplicitAny, Decl(thisTypeInFunctions.ts, 210, 27)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 212, 34)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 212, 39)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 212, 39)) diff --git a/tests/baselines/reference/thisTypeInFunctions.types b/tests/baselines/reference/thisTypeInFunctions.types index 2c334b2caed..e5f6a561d59 100644 --- a/tests/baselines/reference/thisTypeInFunctions.types +++ b/tests/baselines/reference/thisTypeInFunctions.types @@ -1,5 +1,11 @@ === tests/cases/conformance/types/thisType/thisTypeInFunctions.ts === // body checking +class B { +>B : B + + n: number; +>n : number +} class C { >C : C @@ -70,12 +76,6 @@ class D extends C { } >D : D >C : C -class B { ->B : B - - n: number; ->n : number -} interface I { >I : I @@ -952,6 +952,19 @@ b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) >d2 : Derived2 >implicit : (this: Derived2) => number +// union assignability + +let b1b2: Base1 | Base2; +>b1b2 : Base1 | Base2 +>Base1 : Base1 +>Base2 : Base2 + +b1b2.implicit(); +>b1b2.implicit() : number +>b1b2.implicit : ((this: Base1) => number) | ((this: Base2) => number) +>b1b2 : Base1 | Base2 +>implicit : ((this: Base1) => number) | ((this: Base2) => number) + ////// use this-type for construction with new //// function InterfaceThis(this: I) { >InterfaceThis : (this: I) => void diff --git a/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts index f92b8ab4e15..e5cc9e45ba2 100644 --- a/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts +++ b/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts @@ -1,5 +1,8 @@ // @strictThis: true // body checking +class B { + n: number; +} class C { n: number; explicitThis(this: this, m: number): number { @@ -19,9 +22,6 @@ class C { } } class D extends C { } -class B { - n: number; -} interface I { a: number; explicitVoid1(this: void): number; @@ -185,6 +185,11 @@ d2.implicit = d1.explicit // ok, 'y' in { x, y } (c assignable to f) b1.implicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) +// union assignability + +let b1b2: Base1 | Base2; +b1b2.implicit(); + ////// use this-type for construction with new //// function InterfaceThis(this: I) { this.a = 12; From 41bb4468652243e2df9f1bd563f7544469bb3021 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 8 Feb 2016 16:39:19 -0800 Subject: [PATCH 043/274] Revert unioning of this argument types The right solution is to not instantiate this-types of unions, which is a separate problem more to do with this-class types. --- src/compiler/checker.ts | 8 +- src/compiler/core.ts | 17 ---- .../looseThisTypeInFunctions.errors.txt | 22 +++-- .../reference/looseThisTypeInFunctions.js | 9 +-- .../reference/thisTypeInFunctions.js | 8 -- .../reference/thisTypeInFunctions.symbols | 80 ++++++++----------- .../reference/thisTypeInFunctions.types | 13 --- .../thisType/looseThisTypeInFunctions.ts | 8 +- .../types/thisType/thisTypeInFuncTemp.ts | 36 +++------ .../types/thisType/thisTypeInFunctions.ts | 5 -- 10 files changed, 61 insertions(+), 145 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0acb3a127d5..b9343a2cdbe 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9513,13 +9513,7 @@ namespace ts { const thisArgumentNode = getThisArgumentOfCall(node); const thisArgumentType = thisArgumentNode ? checkExpression(thisArgumentNode) : voidType; const errorNode = reportErrors ? (thisArgumentNode || node) : undefined; - if (thisArgumentType.flags & TypeFlags.UnionOrIntersection) { - const u = thisArgumentType; - if (!forEach(u.types, t => checkTypeRelatedTo(t, signature.thisType, relation, errorNode, headMessage))) { - return false; - } - } - else if (!checkTypeRelatedTo(thisArgumentType, signature.thisType, relation, errorNode, headMessage)) { + if (!checkTypeRelatedTo(thisArgumentType, signature.thisType, relation, errorNode, headMessage)) { return false; } } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index f1f9d93c5d2..21536da36ff 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -91,23 +91,6 @@ namespace ts { return undefined; } - /** - * Iterates through `array` by index and performs the callback on each element of array until the callback - * returns a falsey value, then returns false. - * If no such value is found, the callback is applied to each element of array and `true` is returned. - */ - export function trueForAll(array: T[], callback: (element: T, index: number) => boolean): boolean { - if (array) { - for (let i = 0, len = array.length; i < len; i++) { - if (!callback(array[i], i)) { - return false; - } - } - } - - return true; - } - export function contains(array: T[], value: T): boolean { if (array) { for (const v of array) { diff --git a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt index 4eef7d83f78..caaf7afb09c 100644 --- a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt +++ b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt @@ -1,13 +1,12 @@ tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(21,1): error TS2322: Type '(this: C, m: number) => number' is not assignable to type '(this: void, m: number) => number'. Types of parameters 'this' and 'this' are incompatible. Type 'void' is not assignable to type 'C'. -tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(32,5): error TS1005: ',' expected. -tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(33,27): error TS2339: Property 'length' does not exist on type 'number'. +tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(33,28): error TS2339: Property 'length' does not exist on type 'number'. tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(37,9): error TS2345: Argument of type 'void' is not assignable to parameter of type 'I'. -tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(46,19): error TS2339: Property 'length' does not exist on type 'number'. +tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(46,20): error TS2339: Property 'length' does not exist on type 'number'. -==== tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts (5 errors) ==== +==== tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts (4 errors) ==== interface I { n: number; explicitThis(this: this, m: number): number; @@ -42,12 +41,10 @@ tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(46,19): error }; let i: I = o; let o2: I = { - n: 1001 + n: 1001, explicitThis: function (m) { - ~~~~~~~~~~~~ -!!! error TS1005: ',' expected. - return m + this.n.length; // error, this.n: number, no member 'length' - ~~~~~~ + return m + this.n.length; // error, this.n: number, no member 'length' + ~~~~~~ !!! error TS2339: Property 'length' does not exist on type 'number'. }, } @@ -63,8 +60,7 @@ tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(46,19): error o.implicitThis = c.explicitThis; // ok, implicitThis(this:any) is assignable to explicitThis(this: this) o.implicitThis = i.explicitThis; i.explicitThis = function(m) { - return this.n.length; // error, this.n: number - ~~~~~~ + return this.n.length; // error, this.n: number + ~~~~~~ !!! error TS2339: Property 'length' does not exist on type 'number'. - } - \ No newline at end of file + } \ No newline at end of file diff --git a/tests/baselines/reference/looseThisTypeInFunctions.js b/tests/baselines/reference/looseThisTypeInFunctions.js index ecb9f650716..3b172877e0e 100644 --- a/tests/baselines/reference/looseThisTypeInFunctions.js +++ b/tests/baselines/reference/looseThisTypeInFunctions.js @@ -29,9 +29,9 @@ let o = { }; let i: I = o; let o2: I = { - n: 1001 + n: 1001, explicitThis: function (m) { - return m + this.n.length; // error, this.n: number, no member 'length' + return m + this.n.length; // error, this.n: number, no member 'length' }, } let x = i.explicitThis; @@ -44,9 +44,8 @@ o.implicitThis = c.implicitThis; // ok, implicitThis(this:any) o.implicitThis = c.explicitThis; // ok, implicitThis(this:any) is assignable to explicitThis(this: this) o.implicitThis = i.explicitThis; i.explicitThis = function(m) { - return this.n.length; // error, this.n: number -} - + return this.n.length; // error, this.n: number +} //// [looseThisTypeInFunctions.js] var C = (function () { diff --git a/tests/baselines/reference/thisTypeInFunctions.js b/tests/baselines/reference/thisTypeInFunctions.js index af55603a4b7..8d34f9bc2cf 100644 --- a/tests/baselines/reference/thisTypeInFunctions.js +++ b/tests/baselines/reference/thisTypeInFunctions.js @@ -185,11 +185,6 @@ d2.implicit = d1.explicit // ok, 'y' in { x, y } (c assignable to f) b1.implicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) -// union assignability - -let b1b2: Base1 | Base2; -b1b2.implicit(); - ////// use this-type for construction with new //// function InterfaceThis(this: I) { this.a = 12; @@ -395,9 +390,6 @@ d1.implicit = b2.implicit; // ok, 'y' in D: { x, y } (d assignable e) d2.implicit = d1.explicit; // ok, 'y' in { x, y } (c assignable to f) b1.implicit = d2.implicit; // ok, 'x' and 'y' not in C: { x } (c assignable to f) b1.explicit = d2.implicit; // ok, 'x' and 'y' not in C: { x } (c assignable to f) -// union assignability -var b1b2; -b1b2.implicit(); ////// use this-type for construction with new //// function InterfaceThis() { this.a = 12; diff --git a/tests/baselines/reference/thisTypeInFunctions.symbols b/tests/baselines/reference/thisTypeInFunctions.symbols index 120494c206f..9cd1915fc94 100644 --- a/tests/baselines/reference/thisTypeInFunctions.symbols +++ b/tests/baselines/reference/thisTypeInFunctions.symbols @@ -791,22 +791,10 @@ b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) >d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 176, 3)) >implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) -// union assignability - -let b1b2: Base1 | Base2; ->b1b2 : Symbol(b1b2, Decl(thisTypeInFunctions.ts, 188, 3)) ->Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) ->Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 164, 1)) - -b1b2.implicit(); ->b1b2.implicit : Symbol(implicit, Decl(thisTypeInFunctions.ts, 154, 14), Decl(thisTypeInFunctions.ts, 166, 13)) ->b1b2 : Symbol(b1b2, Decl(thisTypeInFunctions.ts, 188, 3)) ->implicit : Symbol(implicit, Decl(thisTypeInFunctions.ts, 154, 14), Decl(thisTypeInFunctions.ts, 166, 13)) - ////// use this-type for construction with new //// function InterfaceThis(this: I) { ->InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 189, 16)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 192, 23)) +>InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 184, 25)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 187, 23)) >I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) this.a = 12; @@ -815,60 +803,60 @@ function InterfaceThis(this: I) { >a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) } function LiteralTypeThis(this: {x: string}) { ->LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 194, 1)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 195, 25)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 195, 32)) +>LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 189, 1)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 190, 25)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 190, 32)) this.x = "ok"; ->this.x : Symbol(x, Decl(thisTypeInFunctions.ts, 195, 32)) ->this : Symbol(, Decl(thisTypeInFunctions.ts, 195, 30)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 195, 32)) +>this.x : Symbol(x, Decl(thisTypeInFunctions.ts, 190, 32)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 190, 30)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 190, 32)) } function AnyThis(this: any) { ->AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 197, 1)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 198, 17)) +>AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 192, 1)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 193, 17)) this.x = "ok"; } let interfaceThis = new InterfaceThis(); ->interfaceThis : Symbol(interfaceThis, Decl(thisTypeInFunctions.ts, 201, 3)) ->InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 189, 16)) +>interfaceThis : Symbol(interfaceThis, Decl(thisTypeInFunctions.ts, 196, 3)) +>InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 184, 25)) let literalTypeThis = new LiteralTypeThis(); ->literalTypeThis : Symbol(literalTypeThis, Decl(thisTypeInFunctions.ts, 202, 3)) ->LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 194, 1)) +>literalTypeThis : Symbol(literalTypeThis, Decl(thisTypeInFunctions.ts, 197, 3)) +>LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 189, 1)) let anyThis = new AnyThis(); ->anyThis : Symbol(anyThis, Decl(thisTypeInFunctions.ts, 203, 3)) ->AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 197, 1)) +>anyThis : Symbol(anyThis, Decl(thisTypeInFunctions.ts, 198, 3)) +>AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 192, 1)) //// type parameter inference //// declare var f: { ->f : Symbol(f, Decl(thisTypeInFunctions.ts, 206, 11)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 201, 11)) (this: void, x: number): number, ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 207, 5)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 207, 16)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 202, 5)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 202, 16)) call(this: (...argArray: any[]) => U, ...argArray: any[]): U; ->call : Symbol(call, Decl(thisTypeInFunctions.ts, 207, 36)) ->U : Symbol(U, Decl(thisTypeInFunctions.ts, 208, 9)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 208, 12)) ->argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 208, 19)) ->U : Symbol(U, Decl(thisTypeInFunctions.ts, 208, 9)) ->argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 208, 44)) ->U : Symbol(U, Decl(thisTypeInFunctions.ts, 208, 9)) +>call : Symbol(call, Decl(thisTypeInFunctions.ts, 202, 36)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 203, 9)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 203, 12)) +>argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 203, 19)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 203, 9)) +>argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 203, 44)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 203, 9)) }; let n: number = f.call(12); ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 210, 3)) ->f.call : Symbol(call, Decl(thisTypeInFunctions.ts, 207, 36)) ->f : Symbol(f, Decl(thisTypeInFunctions.ts, 206, 11)) ->call : Symbol(call, Decl(thisTypeInFunctions.ts, 207, 36)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 205, 3)) +>f.call : Symbol(call, Decl(thisTypeInFunctions.ts, 202, 36)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 201, 11)) +>call : Symbol(call, Decl(thisTypeInFunctions.ts, 202, 36)) function missingTypeIsImplicitAny(this, a: number) { return a; } ->missingTypeIsImplicitAny : Symbol(missingTypeIsImplicitAny, Decl(thisTypeInFunctions.ts, 210, 27)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 212, 34)) ->a : Symbol(a, Decl(thisTypeInFunctions.ts, 212, 39)) ->a : Symbol(a, Decl(thisTypeInFunctions.ts, 212, 39)) +>missingTypeIsImplicitAny : Symbol(missingTypeIsImplicitAny, Decl(thisTypeInFunctions.ts, 205, 27)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 207, 34)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 207, 39)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 207, 39)) diff --git a/tests/baselines/reference/thisTypeInFunctions.types b/tests/baselines/reference/thisTypeInFunctions.types index e5f6a561d59..3922e454c3f 100644 --- a/tests/baselines/reference/thisTypeInFunctions.types +++ b/tests/baselines/reference/thisTypeInFunctions.types @@ -952,19 +952,6 @@ b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) >d2 : Derived2 >implicit : (this: Derived2) => number -// union assignability - -let b1b2: Base1 | Base2; ->b1b2 : Base1 | Base2 ->Base1 : Base1 ->Base2 : Base2 - -b1b2.implicit(); ->b1b2.implicit() : number ->b1b2.implicit : ((this: Base1) => number) | ((this: Base2) => number) ->b1b2 : Base1 | Base2 ->implicit : ((this: Base1) => number) | ((this: Base2) => number) - ////// use this-type for construction with new //// function InterfaceThis(this: I) { >InterfaceThis : (this: I) => void diff --git a/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts index 3e8bdb11170..b151961e324 100644 --- a/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts +++ b/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts @@ -28,9 +28,9 @@ let o = { }; let i: I = o; let o2: I = { - n: 1001 + n: 1001, explicitThis: function (m) { - return m + this.n.length; // error, this.n: number, no member 'length' + return m + this.n.length; // error, this.n: number, no member 'length' }, } let x = i.explicitThis; @@ -43,5 +43,5 @@ o.implicitThis = c.implicitThis; // ok, implicitThis(this:any) o.implicitThis = c.explicitThis; // ok, implicitThis(this:any) is assignable to explicitThis(this: this) o.implicitThis = i.explicitThis; i.explicitThis = function(m) { - return this.n.length; // error, this.n: number -} + return this.n.length; // error, this.n: number +} \ No newline at end of file diff --git a/tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts b/tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts index 2f4873031fb..e4ae3deb171 100644 --- a/tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts +++ b/tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts @@ -1,27 +1,9 @@ -// @strictThis: true -// 1. contextual typing predicate is wrong (currently: method2: function () ...) -// () -> yes (allParametersAreUntyped=t, noThisParameter=t, noTypeParameters=t) -// ok .. fixed? -// 2. contextual typing of this doesn't seem to work -// strictThis was turned off. DUH. -// 3. when it DID work, it was giving bogus types with strictThis OFF (see the last example) -interface T { - (x: number): void; -} -interface I { - n: number - method(this: this): number; - method2(this: this): number; -} -let i: I = { - n: 12, - method: function(this) { // this: I - return this.n.length; // error, 'number' has no property 'length' - }, - method2: function() { // this: I - return this.n.length; // error, 'number' has no property 'length' - } -} -i.method = function () { return this.n.length } // this: I -i.method = function (this) { return this.n.length } // this: I -var t: T = function (this, y) { } // yes! (but this: any NOT number!!) \ No newline at end of file +//@strictThis: true +interface A { a: number; m(this: this): number } +interface B { b: number, m(this: this): number } +interface C { c: number; m(): number } +let a: A; +let ab: A | B; +let abc: A | B | C; +// ab.m().length; +abc.m().length; // should be OK? this: any, right? \ No newline at end of file diff --git a/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts index e5cc9e45ba2..8676d12c5ab 100644 --- a/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts +++ b/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts @@ -185,11 +185,6 @@ d2.implicit = d1.explicit // ok, 'y' in { x, y } (c assignable to f) b1.implicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) -// union assignability - -let b1b2: Base1 | Base2; -b1b2.implicit(); - ////// use this-type for construction with new //// function InterfaceThis(this: I) { this.a = 12; From 63c690813fe82138be9f7d53c814f05992eece74 Mon Sep 17 00:00:00 2001 From: vilicvane Date: Tue, 9 Feb 2016 22:23:43 +0800 Subject: [PATCH 044/274] Create createHash and getModifiedTime under sys, and refactor implementation into compiler host --- src/compiler/program.ts | 39 +++++++++++++++++++++++++++++++++- src/compiler/sys.ts | 46 +++++++++-------------------------------- 2 files changed, 48 insertions(+), 37 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 9852b2354e2..d9d23a92186 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -559,6 +559,12 @@ namespace ts { sourceMap: false, }; + interface OutputFingerprint { + hash: string; + byteOrderMark: boolean; + mtime: Date; + } + export function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost { const existingDirectories: Map = {}; @@ -609,11 +615,42 @@ namespace ts { } } + const outputFingerprints: Map = + options.watch && sys.createHash && sys.getModifiedTime ? {} : undefined; + + const fileWriter: typeof sys.writeFile = outputFingerprints ? + (fileName, data, writeByteOrderMark) => { + const hash = sys.createHash(data); + const mtimeBefore = sys.getModifiedTime(fileName); + + if (mtimeBefore && outputFingerprints.hasOwnProperty(fileName)) { + const fingerprint = outputFingerprints[fileName]; + + // If output has not been changed, and the file has no external modification + if (fingerprint.byteOrderMark === writeByteOrderMark && + fingerprint.hash === hash && + fingerprint.mtime.getTime() === mtimeBefore.getTime()) { + return; + } + } + + sys.writeFile(fileName, data, writeByteOrderMark); + + const mtimeAfter = sys.getModifiedTime(fileName); + + outputFingerprints[fileName] = { + hash, + byteOrderMark: writeByteOrderMark, + mtime: mtimeAfter + }; + } : + (fileName, data, writeByteOrderMark) => sys.writeFile(fileName, data, writeByteOrderMark); + function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) { try { const start = new Date().getTime(); ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName))); - sys.writeFile(fileName, data, writeByteOrderMark); + fileWriter(fileName, data, writeByteOrderMark); ioWriteTime += new Date().getTime() - start; } catch (e) { diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 69277f65a92..3f33df61a0f 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -20,6 +20,8 @@ namespace ts { getExecutingFilePath(): string; getCurrentDirectory(): string; readDirectory(path: string, extension?: string, exclude?: string[]): string[]; + getModifiedTime?(path: string): Date; + createHash?(data: string): string; getMemoryUsage?(): number; exit(exitCode?: number): void; } @@ -39,15 +41,6 @@ namespace ts { referenceCount: number; } - interface OutputFingerprint { - hash: string; - mtime: Date; - } - - interface OutputFingerprintMap { - [fileName: string]: OutputFingerprint; - } - declare var require: any; declare var module: any; declare var process: any; @@ -449,26 +442,12 @@ namespace ts { return buffer.toString("utf8"); } - const outputFingerprintMap: OutputFingerprintMap = {}; - function writeFile(fileName: string, data: string, writeByteOrderMark?: boolean): void { // If a BOM is required, emit one if (writeByteOrderMark) { data = "\uFEFF" + data; } - const md5 = getMd5(data); - const mtimeBefore = _fs.existsSync(fileName) && _fs.statSync(fileName).mtime; - - if (mtimeBefore && outputFingerprintMap.hasOwnProperty(fileName)) { - const fingerprint = outputFingerprintMap[fileName]; - - // If output has not been changed, and the file has no external modification - if (fingerprint.hash === md5 && fingerprint.mtime.getTime() === mtimeBefore.getTime()) { - return; - } - } - let fd: number; try { @@ -480,19 +459,6 @@ namespace ts { _fs.closeSync(fd); } } - - const mtimeAfter = _fs.statSync(fileName).mtime; - - outputFingerprintMap[fileName] = { - hash: md5, - mtime: mtimeAfter - }; - } - - function getMd5(data: string): string { - const hash = _crypto.createHash("md5"); - hash.update(data); - return hash.digest("hex"); } function getCanonicalPath(path: string): string { @@ -593,6 +559,14 @@ namespace ts { return process.cwd(); }, readDirectory, + getModifiedTime(path) { + return _fs.existsSync(path) && _fs.statSync(path).mtime; + }, + createHash(data) { + const hash = _crypto.createHash("md5"); + hash.update(data); + return hash.digest("hex"); + }, getMemoryUsage() { if (global.gc) { global.gc(); From acf965a20e0f238aac6cf48649ab78fec867213b Mon Sep 17 00:00:00 2001 From: vilicvane Date: Wed, 10 Feb 2016 08:47:52 +0800 Subject: [PATCH 045/274] Refine implementation --- src/compiler/program.ts | 2 +- src/compiler/sys.ts | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index d9d23a92186..33c2da50c1a 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -623,7 +623,7 @@ namespace ts { const hash = sys.createHash(data); const mtimeBefore = sys.getModifiedTime(fileName); - if (mtimeBefore && outputFingerprints.hasOwnProperty(fileName)) { + if (mtimeBefore && hasProperty(outputFingerprints, fileName)) { const fingerprint = outputFingerprints[fileName]; // If output has not been changed, and the file has no external modification diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 3f33df61a0f..9f7903d4201 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -229,6 +229,7 @@ namespace ts { const _path = require("path"); const _os = require("os"); const _crypto = require("crypto"); + let hash: any; // average async stat takes about 30 microseconds // set chunk size to do 30 files in < 1 millisecond @@ -560,10 +561,18 @@ namespace ts { }, readDirectory, getModifiedTime(path) { - return _fs.existsSync(path) && _fs.statSync(path).mtime; + try { + return _fs.statSync(path).mtime; + } + catch (e) { + return undefined; + } }, createHash(data) { - const hash = _crypto.createHash("md5"); + if (!hash) { + hash = _crypto.createHash("md5"); + } + hash.update(data); return hash.digest("hex"); }, From 0282c0463d975c48d9cdda429690a36544941e97 Mon Sep 17 00:00:00 2001 From: vilicvane Date: Wed, 10 Feb 2016 08:50:22 +0800 Subject: [PATCH 046/274] Revert hash object caching --- src/compiler/sys.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 9f7903d4201..99008d4cc7e 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -229,7 +229,6 @@ namespace ts { const _path = require("path"); const _os = require("os"); const _crypto = require("crypto"); - let hash: any; // average async stat takes about 30 microseconds // set chunk size to do 30 files in < 1 millisecond @@ -569,10 +568,7 @@ namespace ts { } }, createHash(data) { - if (!hash) { - hash = _crypto.createHash("md5"); - } - + const hash = _crypto.createHash("md5"); hash.update(data); return hash.digest("hex"); }, From a4813052922da694a34474d884f0f633482fd588 Mon Sep 17 00:00:00 2001 From: vilicvane Date: Thu, 11 Feb 2016 16:38:21 +0800 Subject: [PATCH 047/274] Reorganize related functions --- src/compiler/program.ts | 56 +++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 33c2da50c1a..0f98b46d933 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -615,42 +615,50 @@ namespace ts { } } - const outputFingerprints: Map = - options.watch && sys.createHash && sys.getModifiedTime ? {} : undefined; + let outputFingerprints: Map; - const fileWriter: typeof sys.writeFile = outputFingerprints ? - (fileName, data, writeByteOrderMark) => { - const hash = sys.createHash(data); - const mtimeBefore = sys.getModifiedTime(fileName); + function writeFileIfUpdated(fileName: string, data: string, writeByteOrderMark: boolean): void { + if (!outputFingerprints) { + outputFingerprints = {}; + } - if (mtimeBefore && hasProperty(outputFingerprints, fileName)) { - const fingerprint = outputFingerprints[fileName]; + const hash = sys.createHash(data); + const mtimeBefore = sys.getModifiedTime(fileName); - // If output has not been changed, and the file has no external modification - if (fingerprint.byteOrderMark === writeByteOrderMark && - fingerprint.hash === hash && - fingerprint.mtime.getTime() === mtimeBefore.getTime()) { - return; - } + if (mtimeBefore && hasProperty(outputFingerprints, fileName)) { + const fingerprint = outputFingerprints[fileName]; + + // If output has not been changed, and the file has no external modification + if (fingerprint.byteOrderMark === writeByteOrderMark && + fingerprint.hash === hash && + fingerprint.mtime.getTime() === mtimeBefore.getTime()) { + return; } + } - sys.writeFile(fileName, data, writeByteOrderMark); + sys.writeFile(fileName, data, writeByteOrderMark); - const mtimeAfter = sys.getModifiedTime(fileName); + const mtimeAfter = sys.getModifiedTime(fileName); - outputFingerprints[fileName] = { - hash, - byteOrderMark: writeByteOrderMark, - mtime: mtimeAfter - }; - } : - (fileName, data, writeByteOrderMark) => sys.writeFile(fileName, data, writeByteOrderMark); + outputFingerprints[fileName] = { + hash, + byteOrderMark: writeByteOrderMark, + mtime: mtimeAfter + }; + } function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) { try { const start = new Date().getTime(); ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName))); - fileWriter(fileName, data, writeByteOrderMark); + + if (options.watch && sys.createHash && sys.getModifiedTime) { + writeFileIfUpdated(fileName, data, writeByteOrderMark); + } + else { + sys.writeFile(fileName, data, writeByteOrderMark); + } + ioWriteTime += new Date().getTime() - start; } catch (e) { From 26cc99b92d63540bbd7792415a9f82a1e9936106 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 14 Feb 2016 18:41:38 -0800 Subject: [PATCH 048/274] Introduce -strictNullChecks compiler option --- src/compiler/commandLineParser.ts | 5 +++++ src/compiler/diagnosticMessages.json | 4 ++++ src/compiler/types.ts | 1 + 3 files changed, 10 insertions(+) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 86d073f7d49..bdc586b6037 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -326,6 +326,11 @@ namespace ts { name: "noImplicitUseStrict", type: "boolean", description: Diagnostics.Do_not_emit_use_strict_directives_in_module_output + }, + { + name: "strictNullChecks", + type: "boolean", + description: Diagnostics.Enable_strict_null_checks } ]; diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 25b86e67d34..6978a9ad611 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2576,6 +2576,10 @@ "category": "Message", "code": 6112 }, + "Enable strict null checks.": { + "category": "Message", + "code": 6113 + }, "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 6b9f49cac01..3e59a623c2f 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2420,6 +2420,7 @@ namespace ts { allowSyntheticDefaultImports?: boolean; allowJs?: boolean; noImplicitUseStrict?: boolean; + strictNullChecks?: boolean; /* @internal */ stripInternal?: boolean; // Skip checking lib.d.ts to help speed up tests. From 8e926035b7e17533b205d06d4c60a89c21238e00 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 14 Feb 2016 18:59:58 -0800 Subject: [PATCH 049/274] Parsing of nullable types --- src/compiler/parser.ts | 23 +++++++++++++++++------ src/compiler/types.ts | 8 +++++++- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 66d33f9d7d9..16ee3eb1627 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -127,7 +127,8 @@ namespace ts { case SyntaxKind.IntersectionType: return visitNodes(cbNodes, (node).types); case SyntaxKind.ParenthesizedType: - return visitNode(cbNode, (node).type); + case SyntaxKind.NullableType: + return visitNode(cbNode, (node).type); case SyntaxKind.ObjectBindingPattern: case SyntaxKind.ArrayBindingPattern: return visitNodes(cbNodes, (node).elements); @@ -2413,11 +2414,21 @@ namespace ts { function parseArrayTypeOrHigher(): TypeNode { let type = parseNonArrayType(); - while (!scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.OpenBracketToken)) { - parseExpected(SyntaxKind.CloseBracketToken); - const node = createNode(SyntaxKind.ArrayType, type.pos); - node.elementType = type; - type = finishNode(node); + while (!scanner.hasPrecedingLineBreak()) { + if (parseOptional(SyntaxKind.OpenBracketToken)) { + parseExpected(SyntaxKind.CloseBracketToken); + const node = createNode(SyntaxKind.ArrayType, type.pos); + node.elementType = type; + type = finishNode(node); + } + else if (parseOptional(SyntaxKind.QuestionToken)) { + const node = createNode(SyntaxKind.NullableType, type.pos); + node.type = type; + type = finishNode(node); + } + else { + break; + } } return type; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 3e59a623c2f..c2e5b166815 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -208,6 +208,7 @@ namespace ts { ParenthesizedType, ThisType, StringLiteralType, + NullableType, // Binding patterns ObjectBindingPattern, ArrayBindingPattern, @@ -353,7 +354,7 @@ namespace ts { FirstFutureReservedWord = ImplementsKeyword, LastFutureReservedWord = YieldKeyword, FirstTypeNode = TypePredicate, - LastTypeNode = StringLiteralType, + LastTypeNode = NullableType, FirstPunctuation = OpenBraceToken, LastPunctuation = CaretEqualsToken, FirstToken = Unknown, @@ -777,6 +778,11 @@ namespace ts { _stringLiteralTypeBrand: any; } + // @kind(SyntaxKind.NullableType) + export interface NullableTypeNode extends TypeNode { + type: TypeNode; + } + // @kind(SyntaxKind.StringLiteral) export interface StringLiteral extends LiteralExpression { _stringLiteralBrand: any; From 26e371d7bd985361c2a251dce5707129079cf362 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 14 Feb 2016 19:15:04 -0800 Subject: [PATCH 050/274] Use TypeFlags.Undefined for both undefined and null types --- src/compiler/checker.ts | 22 +++++++++++----------- src/compiler/types.ts | 13 ++++++------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6b43b3802c2..4667ff64d95 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -115,8 +115,8 @@ namespace ts { const booleanType = createIntrinsicType(TypeFlags.Boolean, "boolean"); const esSymbolType = createIntrinsicType(TypeFlags.ESSymbol, "symbol"); const voidType = createIntrinsicType(TypeFlags.Void, "void"); - const undefinedType = createIntrinsicType(TypeFlags.Undefined | TypeFlags.ContainsUndefinedOrNull, "undefined"); - const nullType = createIntrinsicType(TypeFlags.Null | TypeFlags.ContainsUndefinedOrNull, "null"); + const undefinedType = createIntrinsicType(TypeFlags.Undefined | TypeFlags.ContainsUndefined, "undefined"); + const nullType = createIntrinsicType(TypeFlags.Undefined | TypeFlags.ContainsUndefined, "null"); const unknownType = createIntrinsicType(TypeFlags.Any, "unknown"); const emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); @@ -210,7 +210,7 @@ namespace ts { }, "undefined": { type: undefinedType, - flags: TypeFlags.ContainsUndefinedOrNull + flags: TypeFlags.ContainsUndefined } }; @@ -6244,7 +6244,7 @@ namespace ts { // A type is array-like if it is a reference to the global Array or global ReadonlyArray type, // or if it is not the undefined or null type and if it is assignable to ReadonlyArray return type.flags & TypeFlags.Reference && ((type).target === globalArrayType || (type).target === globalReadonlyArrayType) || - !(type.flags & (TypeFlags.Undefined | TypeFlags.Null)) && isTypeAssignableTo(type, anyReadonlyArrayType); + !(type.flags & TypeFlags.Undefined) && isTypeAssignableTo(type, anyReadonlyArrayType); } function isTupleLikeType(type: Type): boolean { @@ -6308,7 +6308,7 @@ namespace ts { function getWidenedType(type: Type): Type { if (type.flags & TypeFlags.RequiresWidening) { - if (type.flags & (TypeFlags.Undefined | TypeFlags.Null)) { + if (type.flags & TypeFlags.Undefined) { return anyType; } if (type.flags & TypeFlags.PredicateType) { @@ -6363,7 +6363,7 @@ namespace ts { if (type.flags & TypeFlags.ObjectLiteral) { for (const p of getPropertiesOfObjectType(type)) { const t = getTypeOfSymbol(p); - if (t.flags & TypeFlags.ContainsUndefinedOrNull) { + if (t.flags & TypeFlags.ContainsUndefined) { if (!reportWideningErrorsInType(t)) { error(p.valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, p.name, typeToString(getWidenedType(t))); } @@ -6407,7 +6407,7 @@ namespace ts { } function reportErrorsFromWidening(declaration: Declaration, type: Type) { - if (produceDiagnostics && compilerOptions.noImplicitAny && type.flags & TypeFlags.ContainsUndefinedOrNull) { + if (produceDiagnostics && compilerOptions.noImplicitAny && type.flags & TypeFlags.ContainsUndefined) { // Report implicit any error within type if possible, otherwise report error on declaration if (!reportWideningErrorsInType(type)) { reportImplicitAnyError(declaration, type); @@ -11087,8 +11087,8 @@ namespace ts { // as having the primitive type Number. If one operand is the null or undefined value, // it is treated as having the type of the other operand. // The result is always of the Number primitive type. - if (leftType.flags & (TypeFlags.Undefined | TypeFlags.Null)) leftType = rightType; - if (rightType.flags & (TypeFlags.Undefined | TypeFlags.Null)) rightType = leftType; + if (leftType.flags & TypeFlags.Undefined) leftType = rightType; + if (rightType.flags & TypeFlags.Undefined) rightType = leftType; let suggestedOperator: SyntaxKind; // if a user tries to apply a bitwise operator to 2 boolean operands @@ -11115,8 +11115,8 @@ namespace ts { // or at least one of the operands to be of type Any or the String primitive type. // If one operand is the null or undefined value, it is treated as having the type of the other operand. - if (leftType.flags & (TypeFlags.Undefined | TypeFlags.Null)) leftType = rightType; - if (rightType.flags & (TypeFlags.Undefined | TypeFlags.Null)) rightType = leftType; + if (leftType.flags & TypeFlags.Undefined) leftType = rightType; + if (rightType.flags & TypeFlags.Undefined) rightType = leftType; let resultType: Type; if (isTypeOfKind(leftType, TypeFlags.NumberLike) && isTypeOfKind(rightType, TypeFlags.NumberLike)) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index c2e5b166815..17a50a1c571 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2074,8 +2074,7 @@ namespace ts { Number = 0x00000004, Boolean = 0x00000008, Void = 0x00000010, - Undefined = 0x00000020, - Null = 0x00000040, + Undefined = 0x00000020, // Undefined or null Enum = 0x00000080, // Enum type StringLiteral = 0x00000100, // String literal type TypeParameter = 0x00000200, // Type parameter @@ -2093,7 +2092,7 @@ namespace ts { /* @internal */ FreshObjectLiteral = 0x00100000, // Fresh object literal type /* @internal */ - ContainsUndefinedOrNull = 0x00200000, // Type is or contains Undefined or Null type + ContainsUndefined = 0x00200000, // Type is or contains undefined type /* @internal */ ContainsObjectLiteral = 0x00400000, // Type is or contains object literal type /* @internal */ @@ -2104,18 +2103,18 @@ namespace ts { PredicateType = 0x08000000, // Predicate types are also Boolean types, but should not be considered Intrinsics - there's no way to capture this with flags /* @internal */ - Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null, + Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined, /* @internal */ - Primitive = String | Number | Boolean | ESSymbol | Void | Undefined | Null | StringLiteral | Enum, + Primitive = String | Number | Boolean | ESSymbol | Void | Undefined | StringLiteral | Enum, StringLike = String | StringLiteral, NumberLike = Number | Enum, ObjectType = Class | Interface | Reference | Tuple | Anonymous, UnionOrIntersection = Union | Intersection, StructuredType = ObjectType | Union | Intersection, /* @internal */ - RequiresWidening = ContainsUndefinedOrNull | ContainsObjectLiteral | PredicateType, + RequiresWidening = ContainsUndefined | ContainsObjectLiteral | PredicateType, /* @internal */ - PropagatingFlags = ContainsUndefinedOrNull | ContainsObjectLiteral | ContainsAnyFunctionType + PropagatingFlags = ContainsUndefined | ContainsObjectLiteral | ContainsAnyFunctionType } export type DestructuringPattern = BindingPattern | ObjectLiteralExpression | ArrayLiteralExpression; From 98b6a5ad11f3ac8d0cec8c6358468b08079dbf90 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 15 Feb 2016 09:23:40 -0800 Subject: [PATCH 051/274] Make undefined and null assignable to each other --- src/compiler/checker.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4667ff64d95..2de8c86e5fd 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5415,8 +5415,7 @@ namespace ts { } if (isTypeAny(target)) return Ternary.True; - if (source === undefinedType) return Ternary.True; - if (source === nullType && target !== undefinedType) return Ternary.True; + if (source.flags & TypeFlags.Undefined) return Ternary.True; if (source.flags & TypeFlags.Enum && target === numberType) return Ternary.True; if (source.flags & TypeFlags.Enum && target.flags & TypeFlags.Enum) { if (result = enumRelatedTo(source, target)) { From e79df80e224957449f18608db6d1fdadc1646629 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 15 Feb 2016 09:24:20 -0800 Subject: [PATCH 052/274] Accepting new baselines --- tests/baselines/reference/arrayLiteralWidened.types | 2 +- tests/baselines/reference/arrayLiterals2ES5.types | 2 +- .../reference/destructuringVariableDeclaration1ES5.types | 4 ++-- .../reference/destructuringVariableDeclaration1ES6.types | 4 ++-- .../baselines/reference/logicalOrOperatorWithEveryType.types | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/baselines/reference/arrayLiteralWidened.types b/tests/baselines/reference/arrayLiteralWidened.types index 9599db2dff5..83db7046eed 100644 --- a/tests/baselines/reference/arrayLiteralWidened.types +++ b/tests/baselines/reference/arrayLiteralWidened.types @@ -19,7 +19,7 @@ var a = [undefined, undefined]; var b = [[], [null, null]]; // any[][] >b : any[][] ->[[], [null, null]] : null[][] +>[[], [null, null]] : undefined[][] >[] : undefined[] >[null, null] : null[] >null : null diff --git a/tests/baselines/reference/arrayLiterals2ES5.types b/tests/baselines/reference/arrayLiterals2ES5.types index a9cf31611c2..cbfb620fb00 100644 --- a/tests/baselines/reference/arrayLiterals2ES5.types +++ b/tests/baselines/reference/arrayLiterals2ES5.types @@ -130,7 +130,7 @@ var temp2: [number[], string[]] = [[1, 2, 3], ["hello", "string"]]; var temp3 = [undefined, null, undefined]; >temp3 : any[] ->[undefined, null, undefined] : null[] +>[undefined, null, undefined] : undefined[] >undefined : undefined >null : null >undefined : undefined diff --git a/tests/baselines/reference/destructuringVariableDeclaration1ES5.types b/tests/baselines/reference/destructuringVariableDeclaration1ES5.types index f8188147a79..aab01926a5a 100644 --- a/tests/baselines/reference/destructuringVariableDeclaration1ES5.types +++ b/tests/baselines/reference/destructuringVariableDeclaration1ES5.types @@ -168,7 +168,7 @@ var {f: [f1, f2, { f3: f4, f5 }, , ]} = { f: [1, 2, { f3: 4, f5: 0 }] }; var {g: {g1 = [undefined, null]}}: { g: { g1: any[] } } = { g: { g1: [1, 2] } }; >g : any >g1 : any[] ->[undefined, null] : null[] +>[undefined, null] : undefined[] >undefined : undefined >null : null >g : { g1: any[]; } @@ -184,7 +184,7 @@ var {g: {g1 = [undefined, null]}}: { g: { g1: any[] } } = { g: { g1: [1, 2] } }; var {h: {h1 = [undefined, null]}}: { h: { h1: number[] } } = { h: { h1: [1, 2] } }; >h : any >h1 : number[] ->[undefined, null] : null[] +>[undefined, null] : undefined[] >undefined : undefined >null : null >h : { h1: number[]; } diff --git a/tests/baselines/reference/destructuringVariableDeclaration1ES6.types b/tests/baselines/reference/destructuringVariableDeclaration1ES6.types index 7b4fe5409db..7e98817c052 100644 --- a/tests/baselines/reference/destructuringVariableDeclaration1ES6.types +++ b/tests/baselines/reference/destructuringVariableDeclaration1ES6.types @@ -168,7 +168,7 @@ var {f: [f1, f2, { f3: f4, f5 }, , ]} = { f: [1, 2, { f3: 4, f5: 0 }] }; var {g: {g1 = [undefined, null]}}: { g: { g1: any[] } } = { g: { g1: [1, 2] } }; >g : any >g1 : any[] ->[undefined, null] : null[] +>[undefined, null] : undefined[] >undefined : undefined >null : null >g : { g1: any[]; } @@ -184,7 +184,7 @@ var {g: {g1 = [undefined, null]}}: { g: { g1: any[] } } = { g: { g1: [1, 2] } }; var {h: {h1 = [undefined, null]}}: { h: { h1: number[] } } = { h: { h1: [1, 2] } }; >h : any >h1 : number[] ->[undefined, null] : null[] +>[undefined, null] : undefined[] >undefined : undefined >null : null >h : { h1: number[]; } diff --git a/tests/baselines/reference/logicalOrOperatorWithEveryType.types b/tests/baselines/reference/logicalOrOperatorWithEveryType.types index 4540e35aaf4..609af4ecc94 100644 --- a/tests/baselines/reference/logicalOrOperatorWithEveryType.types +++ b/tests/baselines/reference/logicalOrOperatorWithEveryType.types @@ -572,7 +572,7 @@ var rj9 = null || null; // null || null is any var rj10 = undefined || null; // undefined || null is any >rj10 : any ->undefined || null : null +>undefined || null : undefined >undefined : undefined >null : null From 6d6d2a11bc07c5ab15462362e27164446a3d05bd Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 15 Feb 2016 09:34:14 -0800 Subject: [PATCH 053/274] Introduce nullable types in checker --- src/compiler/checker.ts | 61 ++++++++++++++++++++++++++++++++++++++--- src/compiler/types.ts | 5 +++- 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2de8c86e5fd..4d930b35667 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -51,6 +51,8 @@ namespace ts { const languageVersion = compilerOptions.target || ScriptTarget.ES3; const modulekind = getEmitModuleKind(compilerOptions); const allowSyntheticDefaultImports = typeof compilerOptions.allowSyntheticDefaultImports !== "undefined" ? compilerOptions.allowSyntheticDefaultImports : modulekind === ModuleKind.System; + const strictNullChecks = compilerOptions.strictNullChecks; + const emitResolver = createResolver(); @@ -2340,6 +2342,7 @@ namespace ts { case SyntaxKind.UnionType: case SyntaxKind.IntersectionType: case SyntaxKind.ParenthesizedType: + case SyntaxKind.NullableType: return isDeclarationVisible(node.parent); // Default binding, import specifier and namespace import is visible @@ -4664,6 +4667,14 @@ namespace ts { return links.resolvedType; } + function getTypeFromNullableTypeNode(node: NullableTypeNode): Type { + const links = getNodeLinks(node); + if (!links.resolvedType) { + links.resolvedType = getNullableType(getTypeFromTypeNode(node.type)); + } + return links.resolvedType; + } + function addTypeToSet(typeSet: Type[], type: Type, typeSetKind: TypeFlags) { if (type.flags & typeSetKind) { addTypesToSet(typeSet, (type).types, typeSetKind); @@ -4736,8 +4747,10 @@ namespace ts { return anyType; } if (noSubtypeReduction) { - removeAllButLast(typeSet, undefinedType); - removeAllButLast(typeSet, nullType); + if (!strictNullChecks) { + removeAllButLast(typeSet, undefinedType); + removeAllButLast(typeSet, nullType); + } } else { removeSubtypes(typeSet); @@ -4920,6 +4933,8 @@ namespace ts { return getTypeFromUnionTypeNode(node); case SyntaxKind.IntersectionType: return getTypeFromIntersectionTypeNode(node); + case SyntaxKind.NullableType: + return getTypeFromNullableTypeNode(node); case SyntaxKind.ParenthesizedType: case SyntaxKind.JSDocNullableType: case SyntaxKind.JSDocNonNullableType: @@ -5415,7 +5430,9 @@ namespace ts { } if (isTypeAny(target)) return Ternary.True; - if (source.flags & TypeFlags.Undefined) return Ternary.True; + if (source.flags & TypeFlags.Undefined) { + if (!strictNullChecks || target.flags & TypeFlags.Undefined) return Ternary.True; + } if (source.flags & TypeFlags.Enum && target === numberType) return Ternary.True; if (source.flags & TypeFlags.Enum && target.flags & TypeFlags.Enum) { if (result = enumRelatedTo(source, target)) { @@ -6262,6 +6279,41 @@ namespace ts { return !!(type.flags & TypeFlags.Tuple); } + function isNullableType(type: Type): boolean { + if (type.flags & TypeFlags.Undefined) { + return true; + } + if (type.flags & TypeFlags.Union) { + for (const t of (type as UnionType).types) { + if (t.flags & TypeFlags.Undefined) { + return true; + } + } + } + return false; + } + + function getNullableType(type: Type): Type { + if (!strictNullChecks) { + return type; + } + if (!type.nullableType) { + type.nullableType = isNullableType(type) ? type : getUnionType([type, undefinedType]); + } + return type.nullableType; + } + + function getNonNullableTypeFromUnionType(type: UnionType): Type { + if (!type.nonNullableType) { + type.nonNullableType = removeTypesFromUnionOrIntersection(type, [undefinedType, nullType]); + } + return type.nonNullableType; + } + + function getNonNullableType(type: Type): Type { + return strictNullChecks && type.flags & TypeFlags.Union ? getNonNullableTypeFromUnionType(type as UnionType) : type; + } + function getRegularTypeOfObjectLiteral(type: Type): Type { if (type.flags & TypeFlags.FreshObjectLiteral) { let regularType = (type).regularType; @@ -14988,7 +15040,8 @@ namespace ts { case SyntaxKind.IntersectionType: return checkUnionOrIntersectionType(node); case SyntaxKind.ParenthesizedType: - return checkSourceElement((node).type); + case SyntaxKind.NullableType: + return checkSourceElement((node).type); case SyntaxKind.FunctionDeclaration: return checkFunctionDeclaration(node); case SyntaxKind.Block: diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 17a50a1c571..d7abcc02963 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2125,6 +2125,7 @@ namespace ts { /* @internal */ id: number; // Unique ID symbol?: Symbol; // Symbol associated with type (if any) pattern?: DestructuringPattern; // Destructuring pattern represented by type (if any) + nullableType?: Type; // Cached nullable form of this type } /* @internal */ @@ -2197,7 +2198,9 @@ namespace ts { resolvedProperties: SymbolTable; // Cache of resolved properties } - export interface UnionType extends UnionOrIntersectionType { } + export interface UnionType extends UnionOrIntersectionType { + nonNullableType?: Type; // Cached non-nullable form of type + } export interface IntersectionType extends UnionOrIntersectionType { } From f08f6067e8c86059ee868cb4eb3e0db72b6e0e77 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 15 Feb 2016 09:38:49 -0800 Subject: [PATCH 054/274] Display support for nullable types --- src/compiler/checker.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4d930b35667..96c6642fb26 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -53,7 +53,6 @@ namespace ts { const allowSyntheticDefaultImports = typeof compilerOptions.allowSyntheticDefaultImports !== "undefined" ? compilerOptions.allowSyntheticDefaultImports : modulekind === ModuleKind.System; const strictNullChecks = compilerOptions.strictNullChecks; - const emitResolver = createResolver(); const undefinedSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "undefined"); @@ -1873,6 +1872,10 @@ namespace ts { else if (type.flags & TypeFlags.Tuple) { writeTupleType(type); } + else if (isNullableType(type)) { + writeType(getNonNullableType(type), TypeFormatFlags.InElementType); + writePunctuation(writer, SyntaxKind.QuestionToken); + } else if (type.flags & TypeFlags.UnionOrIntersection) { writeUnionOrIntersectionType(type, flags); } From fa36ff85ca78861fd24586c0403eeb4a1bf50305 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 15 Feb 2016 09:42:16 -0800 Subject: [PATCH 055/274] Don't widen undefined types in unions --- src/compiler/checker.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 96c6642fb26..b17de2a2b74 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6360,6 +6360,10 @@ namespace ts { numberIndexInfo && createIndexInfo(getWidenedType(numberIndexInfo.type), numberIndexInfo.isReadonly)); } + function getWidenedConstituentType(type: Type): Type { + return type.flags & TypeFlags.Undefined ? type : getWidenedType(type); + } + function getWidenedType(type: Type): Type { if (type.flags & TypeFlags.RequiresWidening) { if (type.flags & TypeFlags.Undefined) { @@ -6372,7 +6376,7 @@ namespace ts { return getWidenedTypeOfObjectLiteral(type); } if (type.flags & TypeFlags.Union) { - return getUnionType(map((type).types, getWidenedType), /*noSubtypeReduction*/ true); + return getUnionType(map((type).types, getWidenedConstituentType), /*noSubtypeReduction*/ true); } if (isArrayType(type)) { return createArrayType(getWidenedType((type).typeArguments[0])); From 0d3005b85de012da071b2a11b827ba6126800dfe Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 15 Feb 2016 09:58:49 -0800 Subject: [PATCH 056/274] Support nullable types with expression operators --- src/compiler/checker.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b17de2a2b74..eefc636f5bd 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10880,7 +10880,8 @@ namespace ts { return booleanType; case SyntaxKind.PlusPlusToken: case SyntaxKind.MinusMinusToken: - const ok = checkArithmeticOperandType(node.operand, operandType, Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type); + const ok = checkArithmeticOperandType(node.operand, getNonNullableType(operandType), + Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type); if (ok) { // run check only if former checks succeeded to avoid reporting cascading errors checkReferenceExpression(node.operand, @@ -10894,7 +10895,8 @@ namespace ts { function checkPostfixUnaryExpression(node: PostfixUnaryExpression): Type { const operandType = checkExpression(node.operand); - const ok = checkArithmeticOperandType(node.operand, operandType, Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type); + const ok = checkArithmeticOperandType(node.operand, getNonNullableType(operandType), + Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type); if (ok) { // run check only if former checks succeeded to avoid reporting cascading errors checkReferenceExpression(node.operand, @@ -11148,6 +11150,9 @@ namespace ts { if (leftType.flags & TypeFlags.Undefined) leftType = rightType; if (rightType.flags & TypeFlags.Undefined) rightType = leftType; + leftType = getNonNullableType(leftType); + rightType = getNonNullableType(rightType); + let suggestedOperator: SyntaxKind; // if a user tries to apply a bitwise operator to 2 boolean operands // try and return them a helpful suggestion @@ -11176,6 +11181,9 @@ namespace ts { if (leftType.flags & TypeFlags.Undefined) leftType = rightType; if (rightType.flags & TypeFlags.Undefined) rightType = leftType; + leftType = getNonNullableType(leftType); + rightType = getNonNullableType(rightType); + let resultType: Type; if (isTypeOfKind(leftType, TypeFlags.NumberLike) && isTypeOfKind(rightType, TypeFlags.NumberLike)) { // Operands of an enum type are treated as having the primitive type Number. @@ -11235,7 +11243,7 @@ namespace ts { case SyntaxKind.AmpersandAmpersandToken: return rightType; case SyntaxKind.BarBarToken: - return getUnionType([leftType, rightType]); + return getUnionType([getNonNullableType(leftType), rightType]); case SyntaxKind.EqualsToken: checkAssignmentOperator(rightType); return getRegularTypeOfObjectLiteral(rightType); From 09fa3e5e158b488e42a86ca560394a1a74167af4 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 15 Feb 2016 11:37:36 -0800 Subject: [PATCH 057/274] Ensure empty array literal is assignable to array of non-null type in strict null mode --- src/compiler/checker.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index eefc636f5bd..1464d719478 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -118,6 +118,7 @@ namespace ts { const voidType = createIntrinsicType(TypeFlags.Void, "void"); const undefinedType = createIntrinsicType(TypeFlags.Undefined | TypeFlags.ContainsUndefined, "undefined"); const nullType = createIntrinsicType(TypeFlags.Undefined | TypeFlags.ContainsUndefined, "null"); + const emptyArrayElementType = createIntrinsicType(TypeFlags.Undefined | TypeFlags.ContainsUndefined, "undefined"); const unknownType = createIntrinsicType(TypeFlags.Any, "unknown"); const emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); @@ -5434,7 +5435,7 @@ namespace ts { if (isTypeAny(target)) return Ternary.True; if (source.flags & TypeFlags.Undefined) { - if (!strictNullChecks || target.flags & TypeFlags.Undefined) return Ternary.True; + if (!strictNullChecks || target.flags & TypeFlags.Undefined || source === emptyArrayElementType) return Ternary.True; } if (source.flags & TypeFlags.Enum && target === numberType) return Ternary.True; if (source.flags & TypeFlags.Enum && target.flags & TypeFlags.Enum) { @@ -8222,7 +8223,7 @@ namespace ts { } } } - return createArrayType(elementTypes.length ? getUnionType(elementTypes) : undefinedType); + return createArrayType(elementTypes.length ? getUnionType(elementTypes) : emptyArrayElementType); } function isNumericName(name: DeclarationName): boolean { From 41401c7caeb73d45c08ea8fa2f18d90e6a401458 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 15 Feb 2016 17:02:43 -0800 Subject: [PATCH 058/274] Make types of optional parameters and properties nullable --- src/compiler/checker.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1464d719478..c7e74d86f90 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2677,7 +2677,8 @@ namespace ts { // Use type from type annotation if one is present if (declaration.type) { - return getTypeFromTypeNode(declaration.type); + const type = getTypeFromTypeNode(declaration.type); + return declaration.questionToken ? getNullableType(type) : type; } if (declaration.kind === SyntaxKind.Parameter) { @@ -2692,7 +2693,7 @@ namespace ts { // Use contextual parameter type if one is available const type = getContextuallyTypedParameterType(declaration); if (type) { - return type; + return declaration.questionToken ? getNullableType(type) : type; } } From 586c3ac86fb27282723bcb88907e80bccbf9860a Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 15 Feb 2016 19:26:20 -0800 Subject: [PATCH 059/274] Exclude undefined/null from flags propagation within union types --- src/compiler/checker.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c7e74d86f90..83a149efdc1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4387,10 +4387,12 @@ namespace ts { // It is only necessary to do so if a constituent type might be the undefined type, the null type, the type // of an object literal or the anyFunctionType. This is because there are operations in the type checker // that care about the presence of such types at arbitrary depth in a containing type. - function getPropagatingFlagsOfTypes(types: Type[]): TypeFlags { + function getPropagatingFlagsOfTypes(types: Type[], excludeKinds: TypeFlags): TypeFlags { let result: TypeFlags = 0; for (const type of types) { - result |= type.flags; + if (!(type.flags & excludeKinds)) { + result |= type.flags; + } } return result & TypeFlags.PropagatingFlags; } @@ -4399,7 +4401,8 @@ namespace ts { const id = getTypeListId(typeArguments); let type = target.instantiations[id]; if (!type) { - const flags = TypeFlags.Reference | (typeArguments ? getPropagatingFlagsOfTypes(typeArguments) : 0); + const propagatedFlags = typeArguments ? getPropagatingFlagsOfTypes(typeArguments, /*excludeKinds*/ 0) : 0; + const flags = TypeFlags.Reference | propagatedFlags; type = target.instantiations[id] = createObjectType(flags, target.symbol); type.target = target; type.typeArguments = typeArguments; @@ -4659,7 +4662,8 @@ namespace ts { } function createNewTupleType(elementTypes: Type[]) { - const type = createObjectType(TypeFlags.Tuple | getPropagatingFlagsOfTypes(elementTypes)); + const propagatedFlags = getPropagatingFlagsOfTypes(elementTypes, /*excludeKinds*/ 0); + const type = createObjectType(TypeFlags.Tuple | propagatedFlags); type.elementTypes = elementTypes; return type; } @@ -4766,7 +4770,8 @@ namespace ts { const id = getTypeListId(typeSet); let type = unionTypes[id]; if (!type) { - type = unionTypes[id] = createObjectType(TypeFlags.Union | getPropagatingFlagsOfTypes(typeSet)); + const propagatedFlags = getPropagatingFlagsOfTypes(typeSet, /*excludeKinds*/ TypeFlags.Undefined); + type = unionTypes[id] = createObjectType(TypeFlags.Union | propagatedFlags); type.types = typeSet; } return type; @@ -4800,7 +4805,8 @@ namespace ts { const id = getTypeListId(typeSet); let type = intersectionTypes[id]; if (!type) { - type = intersectionTypes[id] = createObjectType(TypeFlags.Intersection | getPropagatingFlagsOfTypes(typeSet)); + const propagatedFlags = getPropagatingFlagsOfTypes(typeSet, /*excludeKinds*/ TypeFlags.Undefined); + type = intersectionTypes[id] = createObjectType(TypeFlags.Intersection | propagatedFlags); type.types = typeSet; } return type; From bf89530e3621ded10c57716b2c76a18c9845c5ae Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 16 Feb 2016 09:51:49 -0800 Subject: [PATCH 060/274] Add truthy/falsey guards for nullable types --- src/compiler/checker.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 83a149efdc1..2e7595f65be 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6993,6 +6993,10 @@ namespace ts { return type; + function narrowTypeByTruthiness(type: Type, expr: Identifier, assumeTrue: boolean): Type { + return strictNullChecks && assumeTrue && getResolvedSymbol(expr) === symbol ? getNonNullableType(type) : type; + } + function narrowTypeByEquality(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { // Check that we have 'typeof ' on the left and string literal on the right if (expr.left.kind !== SyntaxKind.TypeOfExpression || expr.right.kind !== SyntaxKind.StringLiteral) { @@ -7195,6 +7199,8 @@ namespace ts { // will be a subtype or the same type as the argument. function narrowType(type: Type, expr: Expression, assumeTrue: boolean): Type { switch (expr.kind) { + case SyntaxKind.Identifier: + return narrowTypeByTruthiness(type, expr, assumeTrue) case SyntaxKind.CallExpression: return narrowTypeByTypePredicate(type, expr, assumeTrue); case SyntaxKind.ParenthesizedExpression: From bd12f1b9138f826847667f2c42aa0414c562dcf0 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 16 Feb 2016 11:03:28 -0800 Subject: [PATCH 061/274] Add missing semicolon --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2e7595f65be..f3aece5dcdb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7200,7 +7200,7 @@ namespace ts { function narrowType(type: Type, expr: Expression, assumeTrue: boolean): Type { switch (expr.kind) { case SyntaxKind.Identifier: - return narrowTypeByTruthiness(type, expr, assumeTrue) + return narrowTypeByTruthiness(type, expr, assumeTrue); case SyntaxKind.CallExpression: return narrowTypeByTypePredicate(type, expr, assumeTrue); case SyntaxKind.ParenthesizedExpression: From a014edf55a61376839682b537463b01d03929c66 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 16 Feb 2016 13:00:21 -0800 Subject: [PATCH 062/274] Address more comments and remove temp test. I added the temp test by mistake. --- src/lib/core.d.ts | 4 ++-- .../conformance/types/thisType/thisTypeInFuncTemp.ts | 9 --------- 2 files changed, 2 insertions(+), 11 deletions(-) delete mode 100644 tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts diff --git a/src/lib/core.d.ts b/src/lib/core.d.ts index 5a94b21b0fb..efc6e12fc6d 100644 --- a/src/lib/core.d.ts +++ b/src/lib/core.d.ts @@ -215,7 +215,7 @@ interface Function { * @param thisArg The object to be used as the this object. * @param argArray A set of arguments to be passed to the function. */ - apply(this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; + apply(this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; apply(this: Function, thisArg: any, argArray?: any): any; /** @@ -223,7 +223,7 @@ interface Function { * @param thisArg The object to be used as the current object. * @param argArray A list of arguments to be passed to the method. */ - call(this: (this: T, ...argArray: any[]) => U, thisArg: T, ...argArray: any[]): U; + call(this: (this: T, ...argArray: any[]) => U, thisArg: T, ...argArray: any[]): U; call(this: Function, thisArg: any, ...argArray: any[]): any; /** diff --git a/tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts b/tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts deleted file mode 100644 index e4ae3deb171..00000000000 --- a/tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts +++ /dev/null @@ -1,9 +0,0 @@ -//@strictThis: true -interface A { a: number; m(this: this): number } -interface B { b: number, m(this: this): number } -interface C { c: number; m(): number } -let a: A; -let ab: A | B; -let abc: A | B | C; -// ab.m().length; -abc.m().length; // should be OK? this: any, right? \ No newline at end of file From 703dcee952d136de19c11f9653384bb0ae23b7db Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Wed, 17 Feb 2016 22:46:37 +0000 Subject: [PATCH 063/274] Allow private and protected class members to be accessible in nested classes --- src/compiler/checker.ts | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ab057d430a4..5436aba1cd3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8950,9 +8950,10 @@ namespace ts { const enclosingClass = enclosingClassDeclaration ? getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingClassDeclaration)) : undefined; - // Private property is accessible if declaring and enclosing class are the same + // Private property is accessible if the property is within the declaring class if (flags & NodeFlags.Private) { - if (declaringClass !== enclosingClass) { + const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop)); + if (!isNodeWithinClass(node, declaringClassDeclaration)) { error(node, Diagnostics.Property_0_is_private_and_only_accessible_within_class_1, symbolToString(prop), typeToString(declaringClass)); return false; } @@ -8965,10 +8966,13 @@ namespace ts { if (left.kind === SyntaxKind.SuperKeyword) { return true; } - // A protected property is accessible in the declaring class and classes derived from it + // A protected property is accessible if the property is within the declaring class or classes derived from it + const typeClassDeclaration = getClassLikeDeclarationOfSymbol(type.symbol); if (!enclosingClass || !hasBaseType(enclosingClass, declaringClass)) { - error(node, Diagnostics.Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses, symbolToString(prop), typeToString(declaringClass)); - return false; + if (!isNodeWithinClass(node, typeClassDeclaration)) { + error(node, Diagnostics.Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses, symbolToString(prop), typeToString(declaringClass)); + return false; + } } // No further restrictions for static properties if (flags & NodeFlags.Static) { @@ -8981,9 +8985,11 @@ namespace ts { } // TODO: why is the first part of this check here? - if (!(getTargetType(type).flags & (TypeFlags.Class | TypeFlags.Interface) && hasBaseType(type, enclosingClass))) { - error(node, Diagnostics.Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1, symbolToString(prop), typeToString(enclosingClass)); - return false; + if (getTargetType(type).flags & (TypeFlags.Class | TypeFlags.Interface)) { + if (!(hasBaseType(type, enclosingClass) || isNodeWithinClass(node, typeClassDeclaration))) { + error(node, Diagnostics.Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1, symbolToString(prop), typeToString(enclosingClass)); + return false; + } } return true; } From 6ce411dd9fc114a91e6ca2fa3436d304b0978787 Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Wed, 17 Feb 2016 22:47:00 +0000 Subject: [PATCH 064/274] Added tests --- ...lassPropertyAccessibleWithinNestedClass.ts | 38 ++++++++++++++++++ ...lassPropertyAccessibleWithinNestedClass.ts | 38 ++++++++++++++++++ ...sPropertyAccessibleWithinNestedSubclass.ts | 39 +++++++++++++++++++ 3 files changed, 115 insertions(+) create mode 100644 tests/cases/conformance/classes/members/accessibility/privateClassPropertyAccessibleWithinNestedClass.ts create mode 100644 tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedClass.ts create mode 100644 tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass.ts diff --git a/tests/cases/conformance/classes/members/accessibility/privateClassPropertyAccessibleWithinNestedClass.ts b/tests/cases/conformance/classes/members/accessibility/privateClassPropertyAccessibleWithinNestedClass.ts new file mode 100644 index 00000000000..a958a5ae624 --- /dev/null +++ b/tests/cases/conformance/classes/members/accessibility/privateClassPropertyAccessibleWithinNestedClass.ts @@ -0,0 +1,38 @@ +// @target: ES5 +// no errors + +class C { + private x: string; + private get y() { return this.x; } + private set y(x) { this.y = this.x; } + private foo() { return this.foo; } + + private static x: string; + private static get y() { return this.x; } + private static set y(x) { this.y = this.x; } + private static foo() { return this.foo; } + private static bar() { this.foo(); } + + private bar() { + class C2 { + private foo() { + let x: C; + var x1 = x.foo; + var x2 = x.bar; + var x3 = x.x; + var x4 = x.y; + + var sx1 = C.x; + var sx2 = C.y; + var sx3 = C.bar; + var sx4 = C.foo; + + let y = new C(); + var y1 = y.foo; + var y2 = y.bar; + var y3 = y.x; + var y4 = y.y; + } + } + } +} \ No newline at end of file diff --git a/tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedClass.ts b/tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedClass.ts new file mode 100644 index 00000000000..3482d1a09e9 --- /dev/null +++ b/tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedClass.ts @@ -0,0 +1,38 @@ +// @target: ES5 +// no errors + +class C { + protected x: string; + protected get y() { return this.x; } + protected set y(x) { this.y = this.x; } + protected foo() { return this.foo; } + + protected static x: string; + protected static get y() { return this.x; } + protected static set y(x) { this.y = this.x; } + protected static foo() { return this.foo; } + protected static bar() { this.foo(); } + + protected bar() { + class C2 { + protected foo() { + let x: C; + var x1 = x.foo; + var x2 = x.bar; + var x3 = x.x; + var x4 = x.y; + + var sx1 = C.x; + var sx2 = C.y; + var sx3 = C.bar; + var sx4 = C.foo; + + let y = new C(); + var y1 = y.foo; + var y2 = y.bar; + var y3 = y.x; + var y4 = y.y; + } + } + } +} \ No newline at end of file diff --git a/tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass.ts b/tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass.ts new file mode 100644 index 00000000000..aae17b8362f --- /dev/null +++ b/tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass.ts @@ -0,0 +1,39 @@ +// @target: ES5 + +class B { + protected x: string; + protected static x: string; +} + +class C extends B { + protected get y() { return this.x; } + protected set y(x) { this.y = this.x; } + protected foo() { return this.x; } + + protected static get y() { return this.x; } + protected static set y(x) { this.y = this.x; } + protected static foo() { return this.x; } + protected static bar() { this.foo(); } + + protected bar() { + class D { + protected foo() { + var c = new C(); + var c1 = c.y; + var c2 = c.x; + var c3 = c.foo; + var c4 = c.bar; + var c5 = c.z; // error + + var sc1 = C.x; + var sc2 = C.y; + var sc3 = C.foo; + var sc4 = C.bar; + } + } + } +} + +class E extends C { + protected z: string; +} \ No newline at end of file From 9a384641874b9bd5ea2c43c6eddf0c36f8432073 Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Wed, 17 Feb 2016 22:47:14 +0000 Subject: [PATCH 065/274] Accept baselines --- ...lassPropertyAccessibleWithinNestedClass.js | 84 ++++++++++ ...ropertyAccessibleWithinNestedClass.symbols | 154 +++++++++++++++++ ...sPropertyAccessibleWithinNestedClass.types | 158 ++++++++++++++++++ ...lassPropertyAccessibleWithinNestedClass.js | 84 ++++++++++ ...ropertyAccessibleWithinNestedClass.symbols | 154 +++++++++++++++++ ...sPropertyAccessibleWithinNestedClass.types | 158 ++++++++++++++++++ ...yAccessibleWithinNestedSubclass.errors.txt | 44 +++++ ...sPropertyAccessibleWithinNestedSubclass.js | 99 +++++++++++ 8 files changed, 935 insertions(+) create mode 100644 tests/baselines/reference/privateClassPropertyAccessibleWithinNestedClass.js create mode 100644 tests/baselines/reference/privateClassPropertyAccessibleWithinNestedClass.symbols create mode 100644 tests/baselines/reference/privateClassPropertyAccessibleWithinNestedClass.types create mode 100644 tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedClass.js create mode 100644 tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedClass.symbols create mode 100644 tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedClass.types create mode 100644 tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedSubclass.errors.txt create mode 100644 tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedSubclass.js diff --git a/tests/baselines/reference/privateClassPropertyAccessibleWithinNestedClass.js b/tests/baselines/reference/privateClassPropertyAccessibleWithinNestedClass.js new file mode 100644 index 00000000000..3bb0a7da3ea --- /dev/null +++ b/tests/baselines/reference/privateClassPropertyAccessibleWithinNestedClass.js @@ -0,0 +1,84 @@ +//// [privateClassPropertyAccessibleWithinNestedClass.ts] +// no errors + +class C { + private x: string; + private get y() { return this.x; } + private set y(x) { this.y = this.x; } + private foo() { return this.foo; } + + private static x: string; + private static get y() { return this.x; } + private static set y(x) { this.y = this.x; } + private static foo() { return this.foo; } + private static bar() { this.foo(); } + + private bar() { + class C2 { + private foo() { + let x: C; + var x1 = x.foo; + var x2 = x.bar; + var x3 = x.x; + var x4 = x.y; + + var sx1 = C.x; + var sx2 = C.y; + var sx3 = C.bar; + var sx4 = C.foo; + + let y = new C(); + var y1 = y.foo; + var y2 = y.bar; + var y3 = y.x; + var y4 = y.y; + } + } + } +} + +//// [privateClassPropertyAccessibleWithinNestedClass.js] +// no errors +var C = (function () { + function C() { + } + Object.defineProperty(C.prototype, "y", { + get: function () { return this.x; }, + set: function (x) { this.y = this.x; }, + enumerable: true, + configurable: true + }); + C.prototype.foo = function () { return this.foo; }; + Object.defineProperty(C, "y", { + get: function () { return this.x; }, + set: function (x) { this.y = this.x; }, + enumerable: true, + configurable: true + }); + C.foo = function () { return this.foo; }; + C.bar = function () { this.foo(); }; + C.prototype.bar = function () { + var C2 = (function () { + function C2() { + } + C2.prototype.foo = function () { + var x; + var x1 = x.foo; + var x2 = x.bar; + var x3 = x.x; + var x4 = x.y; + var sx1 = C.x; + var sx2 = C.y; + var sx3 = C.bar; + var sx4 = C.foo; + var y = new C(); + var y1 = y.foo; + var y2 = y.bar; + var y3 = y.x; + var y4 = y.y; + }; + return C2; + }()); + }; + return C; +}()); diff --git a/tests/baselines/reference/privateClassPropertyAccessibleWithinNestedClass.symbols b/tests/baselines/reference/privateClassPropertyAccessibleWithinNestedClass.symbols new file mode 100644 index 00000000000..dd22887eb23 --- /dev/null +++ b/tests/baselines/reference/privateClassPropertyAccessibleWithinNestedClass.symbols @@ -0,0 +1,154 @@ +=== tests/cases/conformance/classes/members/accessibility/privateClassPropertyAccessibleWithinNestedClass.ts === +// no errors + +class C { +>C : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) + + private x: string; +>x : Symbol(x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) + + private get y() { return this.x; } +>y : Symbol(y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 3, 22), Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 4, 38)) +>this.x : Symbol(x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) +>this : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>x : Symbol(x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) + + private set y(x) { this.y = this.x; } +>y : Symbol(y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 3, 22), Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 4, 38)) +>x : Symbol(x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 5, 18)) +>this.y : Symbol(y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 3, 22), Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 4, 38)) +>this : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>y : Symbol(y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 3, 22), Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 4, 38)) +>this.x : Symbol(x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) +>this : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>x : Symbol(x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) + + private foo() { return this.foo; } +>foo : Symbol(foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 5, 41)) +>this.foo : Symbol(foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 5, 41)) +>this : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>foo : Symbol(foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 5, 41)) + + private static x: string; +>x : Symbol(C.x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 6, 38)) + + private static get y() { return this.x; } +>y : Symbol(C.y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 8, 29), Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 9, 45)) +>this.x : Symbol(C.x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 6, 38)) +>this : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>x : Symbol(C.x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 6, 38)) + + private static set y(x) { this.y = this.x; } +>y : Symbol(C.y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 8, 29), Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 9, 45)) +>x : Symbol(x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 10, 25)) +>this.y : Symbol(C.y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 8, 29), Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 9, 45)) +>this : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>y : Symbol(C.y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 8, 29), Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 9, 45)) +>this.x : Symbol(C.x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 6, 38)) +>this : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>x : Symbol(C.x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 6, 38)) + + private static foo() { return this.foo; } +>foo : Symbol(C.foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 10, 48)) +>this.foo : Symbol(C.foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 10, 48)) +>this : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>foo : Symbol(C.foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 10, 48)) + + private static bar() { this.foo(); } +>bar : Symbol(C.bar, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 11, 45)) +>this.foo : Symbol(C.foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 10, 48)) +>this : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>foo : Symbol(C.foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 10, 48)) + + private bar() { +>bar : Symbol(bar, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 12, 40)) + + class C2 { +>C2 : Symbol(C2, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 14, 19)) + + private foo() { +>foo : Symbol(foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 15, 18)) + + let x: C; +>x : Symbol(x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 17, 19)) +>C : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) + + var x1 = x.foo; +>x1 : Symbol(x1, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 18, 19)) +>x.foo : Symbol(C.foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 5, 41)) +>x : Symbol(x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 17, 19)) +>foo : Symbol(C.foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 5, 41)) + + var x2 = x.bar; +>x2 : Symbol(x2, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 19, 19)) +>x.bar : Symbol(C.bar, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 12, 40)) +>x : Symbol(x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 17, 19)) +>bar : Symbol(C.bar, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 12, 40)) + + var x3 = x.x; +>x3 : Symbol(x3, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 20, 19)) +>x.x : Symbol(x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) +>x : Symbol(x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 17, 19)) +>x : Symbol(x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) + + var x4 = x.y; +>x4 : Symbol(x4, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 21, 19)) +>x.y : Symbol(C.y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 3, 22), Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 4, 38)) +>x : Symbol(x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 17, 19)) +>y : Symbol(C.y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 3, 22), Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 4, 38)) + + var sx1 = C.x; +>sx1 : Symbol(sx1, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 23, 19)) +>C.x : Symbol(C.x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 6, 38)) +>C : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>x : Symbol(C.x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 6, 38)) + + var sx2 = C.y; +>sx2 : Symbol(sx2, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 24, 19)) +>C.y : Symbol(C.y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 8, 29), Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 9, 45)) +>C : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>y : Symbol(C.y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 8, 29), Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 9, 45)) + + var sx3 = C.bar; +>sx3 : Symbol(sx3, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 25, 19)) +>C.bar : Symbol(C.bar, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 11, 45)) +>C : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>bar : Symbol(C.bar, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 11, 45)) + + var sx4 = C.foo; +>sx4 : Symbol(sx4, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 26, 19)) +>C.foo : Symbol(C.foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 10, 48)) +>C : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>foo : Symbol(C.foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 10, 48)) + + let y = new C(); +>y : Symbol(y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 28, 19)) +>C : Symbol(C, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) + + var y1 = y.foo; +>y1 : Symbol(y1, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 29, 19)) +>y.foo : Symbol(C.foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 5, 41)) +>y : Symbol(y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 28, 19)) +>foo : Symbol(C.foo, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 5, 41)) + + var y2 = y.bar; +>y2 : Symbol(y2, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 30, 19)) +>y.bar : Symbol(C.bar, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 12, 40)) +>y : Symbol(y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 28, 19)) +>bar : Symbol(C.bar, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 12, 40)) + + var y3 = y.x; +>y3 : Symbol(y3, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 31, 19)) +>y.x : Symbol(x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) +>y : Symbol(y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 28, 19)) +>x : Symbol(x, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) + + var y4 = y.y; +>y4 : Symbol(y4, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 32, 19)) +>y.y : Symbol(C.y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 3, 22), Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 4, 38)) +>y : Symbol(y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 28, 19)) +>y : Symbol(C.y, Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 3, 22), Decl(privateClassPropertyAccessibleWithinNestedClass.ts, 4, 38)) + } + } + } +} diff --git a/tests/baselines/reference/privateClassPropertyAccessibleWithinNestedClass.types b/tests/baselines/reference/privateClassPropertyAccessibleWithinNestedClass.types new file mode 100644 index 00000000000..ee8eb82b940 --- /dev/null +++ b/tests/baselines/reference/privateClassPropertyAccessibleWithinNestedClass.types @@ -0,0 +1,158 @@ +=== tests/cases/conformance/classes/members/accessibility/privateClassPropertyAccessibleWithinNestedClass.ts === +// no errors + +class C { +>C : C + + private x: string; +>x : string + + private get y() { return this.x; } +>y : string +>this.x : string +>this : this +>x : string + + private set y(x) { this.y = this.x; } +>y : string +>x : string +>this.y = this.x : string +>this.y : string +>this : this +>y : string +>this.x : string +>this : this +>x : string + + private foo() { return this.foo; } +>foo : () => any +>this.foo : () => any +>this : this +>foo : () => any + + private static x: string; +>x : string + + private static get y() { return this.x; } +>y : string +>this.x : string +>this : typeof C +>x : string + + private static set y(x) { this.y = this.x; } +>y : string +>x : string +>this.y = this.x : string +>this.y : string +>this : typeof C +>y : string +>this.x : string +>this : typeof C +>x : string + + private static foo() { return this.foo; } +>foo : () => typeof C.foo +>this.foo : () => typeof C.foo +>this : typeof C +>foo : () => typeof C.foo + + private static bar() { this.foo(); } +>bar : () => void +>this.foo() : () => typeof C.foo +>this.foo : () => typeof C.foo +>this : typeof C +>foo : () => typeof C.foo + + private bar() { +>bar : () => void + + class C2 { +>C2 : C2 + + private foo() { +>foo : () => void + + let x: C; +>x : C +>C : C + + var x1 = x.foo; +>x1 : () => any +>x.foo : () => any +>x : C +>foo : () => any + + var x2 = x.bar; +>x2 : () => void +>x.bar : () => void +>x : C +>bar : () => void + + var x3 = x.x; +>x3 : string +>x.x : string +>x : C +>x : string + + var x4 = x.y; +>x4 : string +>x.y : string +>x : C +>y : string + + var sx1 = C.x; +>sx1 : string +>C.x : string +>C : typeof C +>x : string + + var sx2 = C.y; +>sx2 : string +>C.y : string +>C : typeof C +>y : string + + var sx3 = C.bar; +>sx3 : () => void +>C.bar : () => void +>C : typeof C +>bar : () => void + + var sx4 = C.foo; +>sx4 : () => typeof C.foo +>C.foo : () => typeof C.foo +>C : typeof C +>foo : () => typeof C.foo + + let y = new C(); +>y : C +>new C() : C +>C : typeof C + + var y1 = y.foo; +>y1 : () => any +>y.foo : () => any +>y : C +>foo : () => any + + var y2 = y.bar; +>y2 : () => void +>y.bar : () => void +>y : C +>bar : () => void + + var y3 = y.x; +>y3 : string +>y.x : string +>y : C +>x : string + + var y4 = y.y; +>y4 : string +>y.y : string +>y : C +>y : string + } + } + } +} diff --git a/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedClass.js b/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedClass.js new file mode 100644 index 00000000000..2bc544e046e --- /dev/null +++ b/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedClass.js @@ -0,0 +1,84 @@ +//// [protectedClassPropertyAccessibleWithinNestedClass.ts] +// no errors + +class C { + protected x: string; + protected get y() { return this.x; } + protected set y(x) { this.y = this.x; } + protected foo() { return this.foo; } + + protected static x: string; + protected static get y() { return this.x; } + protected static set y(x) { this.y = this.x; } + protected static foo() { return this.foo; } + protected static bar() { this.foo(); } + + protected bar() { + class C2 { + protected foo() { + let x: C; + var x1 = x.foo; + var x2 = x.bar; + var x3 = x.x; + var x4 = x.y; + + var sx1 = C.x; + var sx2 = C.y; + var sx3 = C.bar; + var sx4 = C.foo; + + let y = new C(); + var y1 = y.foo; + var y2 = y.bar; + var y3 = y.x; + var y4 = y.y; + } + } + } +} + +//// [protectedClassPropertyAccessibleWithinNestedClass.js] +// no errors +var C = (function () { + function C() { + } + Object.defineProperty(C.prototype, "y", { + get: function () { return this.x; }, + set: function (x) { this.y = this.x; }, + enumerable: true, + configurable: true + }); + C.prototype.foo = function () { return this.foo; }; + Object.defineProperty(C, "y", { + get: function () { return this.x; }, + set: function (x) { this.y = this.x; }, + enumerable: true, + configurable: true + }); + C.foo = function () { return this.foo; }; + C.bar = function () { this.foo(); }; + C.prototype.bar = function () { + var C2 = (function () { + function C2() { + } + C2.prototype.foo = function () { + var x; + var x1 = x.foo; + var x2 = x.bar; + var x3 = x.x; + var x4 = x.y; + var sx1 = C.x; + var sx2 = C.y; + var sx3 = C.bar; + var sx4 = C.foo; + var y = new C(); + var y1 = y.foo; + var y2 = y.bar; + var y3 = y.x; + var y4 = y.y; + }; + return C2; + }()); + }; + return C; +}()); diff --git a/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedClass.symbols b/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedClass.symbols new file mode 100644 index 00000000000..ca10d9652e4 --- /dev/null +++ b/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedClass.symbols @@ -0,0 +1,154 @@ +=== tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedClass.ts === +// no errors + +class C { +>C : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) + + protected x: string; +>x : Symbol(x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) + + protected get y() { return this.x; } +>y : Symbol(y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 3, 24), Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 4, 40)) +>this.x : Symbol(x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) +>this : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>x : Symbol(x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) + + protected set y(x) { this.y = this.x; } +>y : Symbol(y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 3, 24), Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 4, 40)) +>x : Symbol(x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 5, 20)) +>this.y : Symbol(y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 3, 24), Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 4, 40)) +>this : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>y : Symbol(y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 3, 24), Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 4, 40)) +>this.x : Symbol(x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) +>this : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>x : Symbol(x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) + + protected foo() { return this.foo; } +>foo : Symbol(foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 5, 43)) +>this.foo : Symbol(foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 5, 43)) +>this : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>foo : Symbol(foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 5, 43)) + + protected static x: string; +>x : Symbol(C.x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 6, 40)) + + protected static get y() { return this.x; } +>y : Symbol(C.y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 8, 31), Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 9, 47)) +>this.x : Symbol(C.x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 6, 40)) +>this : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>x : Symbol(C.x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 6, 40)) + + protected static set y(x) { this.y = this.x; } +>y : Symbol(C.y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 8, 31), Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 9, 47)) +>x : Symbol(x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 10, 27)) +>this.y : Symbol(C.y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 8, 31), Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 9, 47)) +>this : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>y : Symbol(C.y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 8, 31), Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 9, 47)) +>this.x : Symbol(C.x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 6, 40)) +>this : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>x : Symbol(C.x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 6, 40)) + + protected static foo() { return this.foo; } +>foo : Symbol(C.foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 10, 50)) +>this.foo : Symbol(C.foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 10, 50)) +>this : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>foo : Symbol(C.foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 10, 50)) + + protected static bar() { this.foo(); } +>bar : Symbol(C.bar, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 11, 47)) +>this.foo : Symbol(C.foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 10, 50)) +>this : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>foo : Symbol(C.foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 10, 50)) + + protected bar() { +>bar : Symbol(bar, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 12, 42)) + + class C2 { +>C2 : Symbol(C2, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 14, 21)) + + protected foo() { +>foo : Symbol(foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 15, 18)) + + let x: C; +>x : Symbol(x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 17, 19)) +>C : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) + + var x1 = x.foo; +>x1 : Symbol(x1, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 18, 19)) +>x.foo : Symbol(C.foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 5, 43)) +>x : Symbol(x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 17, 19)) +>foo : Symbol(C.foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 5, 43)) + + var x2 = x.bar; +>x2 : Symbol(x2, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 19, 19)) +>x.bar : Symbol(C.bar, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 12, 42)) +>x : Symbol(x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 17, 19)) +>bar : Symbol(C.bar, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 12, 42)) + + var x3 = x.x; +>x3 : Symbol(x3, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 20, 19)) +>x.x : Symbol(x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) +>x : Symbol(x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 17, 19)) +>x : Symbol(x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) + + var x4 = x.y; +>x4 : Symbol(x4, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 21, 19)) +>x.y : Symbol(C.y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 3, 24), Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 4, 40)) +>x : Symbol(x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 17, 19)) +>y : Symbol(C.y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 3, 24), Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 4, 40)) + + var sx1 = C.x; +>sx1 : Symbol(sx1, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 23, 19)) +>C.x : Symbol(C.x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 6, 40)) +>C : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>x : Symbol(C.x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 6, 40)) + + var sx2 = C.y; +>sx2 : Symbol(sx2, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 24, 19)) +>C.y : Symbol(C.y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 8, 31), Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 9, 47)) +>C : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>y : Symbol(C.y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 8, 31), Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 9, 47)) + + var sx3 = C.bar; +>sx3 : Symbol(sx3, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 25, 19)) +>C.bar : Symbol(C.bar, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 11, 47)) +>C : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>bar : Symbol(C.bar, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 11, 47)) + + var sx4 = C.foo; +>sx4 : Symbol(sx4, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 26, 19)) +>C.foo : Symbol(C.foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 10, 50)) +>C : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) +>foo : Symbol(C.foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 10, 50)) + + let y = new C(); +>y : Symbol(y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 28, 19)) +>C : Symbol(C, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 0, 0)) + + var y1 = y.foo; +>y1 : Symbol(y1, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 29, 19)) +>y.foo : Symbol(C.foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 5, 43)) +>y : Symbol(y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 28, 19)) +>foo : Symbol(C.foo, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 5, 43)) + + var y2 = y.bar; +>y2 : Symbol(y2, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 30, 19)) +>y.bar : Symbol(C.bar, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 12, 42)) +>y : Symbol(y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 28, 19)) +>bar : Symbol(C.bar, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 12, 42)) + + var y3 = y.x; +>y3 : Symbol(y3, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 31, 19)) +>y.x : Symbol(x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) +>y : Symbol(y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 28, 19)) +>x : Symbol(x, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 2, 9)) + + var y4 = y.y; +>y4 : Symbol(y4, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 32, 19)) +>y.y : Symbol(C.y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 3, 24), Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 4, 40)) +>y : Symbol(y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 28, 19)) +>y : Symbol(C.y, Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 3, 24), Decl(protectedClassPropertyAccessibleWithinNestedClass.ts, 4, 40)) + } + } + } +} diff --git a/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedClass.types b/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedClass.types new file mode 100644 index 00000000000..f7cff2e6719 --- /dev/null +++ b/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedClass.types @@ -0,0 +1,158 @@ +=== tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedClass.ts === +// no errors + +class C { +>C : C + + protected x: string; +>x : string + + protected get y() { return this.x; } +>y : string +>this.x : string +>this : this +>x : string + + protected set y(x) { this.y = this.x; } +>y : string +>x : string +>this.y = this.x : string +>this.y : string +>this : this +>y : string +>this.x : string +>this : this +>x : string + + protected foo() { return this.foo; } +>foo : () => any +>this.foo : () => any +>this : this +>foo : () => any + + protected static x: string; +>x : string + + protected static get y() { return this.x; } +>y : string +>this.x : string +>this : typeof C +>x : string + + protected static set y(x) { this.y = this.x; } +>y : string +>x : string +>this.y = this.x : string +>this.y : string +>this : typeof C +>y : string +>this.x : string +>this : typeof C +>x : string + + protected static foo() { return this.foo; } +>foo : () => typeof C.foo +>this.foo : () => typeof C.foo +>this : typeof C +>foo : () => typeof C.foo + + protected static bar() { this.foo(); } +>bar : () => void +>this.foo() : () => typeof C.foo +>this.foo : () => typeof C.foo +>this : typeof C +>foo : () => typeof C.foo + + protected bar() { +>bar : () => void + + class C2 { +>C2 : C2 + + protected foo() { +>foo : () => void + + let x: C; +>x : C +>C : C + + var x1 = x.foo; +>x1 : () => any +>x.foo : () => any +>x : C +>foo : () => any + + var x2 = x.bar; +>x2 : () => void +>x.bar : () => void +>x : C +>bar : () => void + + var x3 = x.x; +>x3 : string +>x.x : string +>x : C +>x : string + + var x4 = x.y; +>x4 : string +>x.y : string +>x : C +>y : string + + var sx1 = C.x; +>sx1 : string +>C.x : string +>C : typeof C +>x : string + + var sx2 = C.y; +>sx2 : string +>C.y : string +>C : typeof C +>y : string + + var sx3 = C.bar; +>sx3 : () => void +>C.bar : () => void +>C : typeof C +>bar : () => void + + var sx4 = C.foo; +>sx4 : () => typeof C.foo +>C.foo : () => typeof C.foo +>C : typeof C +>foo : () => typeof C.foo + + let y = new C(); +>y : C +>new C() : C +>C : typeof C + + var y1 = y.foo; +>y1 : () => any +>y.foo : () => any +>y : C +>foo : () => any + + var y2 = y.bar; +>y2 : () => void +>y.bar : () => void +>y : C +>bar : () => void + + var y3 = y.x; +>y3 : string +>y.x : string +>y : C +>x : string + + var y4 = y.y; +>y4 : string +>y.y : string +>y : C +>y : string + } + } + } +} diff --git a/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedSubclass.errors.txt b/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedSubclass.errors.txt new file mode 100644 index 00000000000..0bf38477f70 --- /dev/null +++ b/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedSubclass.errors.txt @@ -0,0 +1,44 @@ +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass.ts(25,28): error TS2339: Property 'z' does not exist on type 'C'. + + +==== tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass.ts (1 errors) ==== + + class B { + protected x: string; + protected static x: string; + } + + class C extends B { + protected get y() { return this.x; } + protected set y(x) { this.y = this.x; } + protected foo() { return this.x; } + + protected static get y() { return this.x; } + protected static set y(x) { this.y = this.x; } + protected static foo() { return this.x; } + protected static bar() { this.foo(); } + + protected bar() { + class D { + protected foo() { + var c = new C(); + var c1 = c.y; + var c2 = c.x; + var c3 = c.foo; + var c4 = c.bar; + var c5 = c.z; // error + ~ +!!! error TS2339: Property 'z' does not exist on type 'C'. + + var sc1 = C.x; + var sc2 = C.y; + var sc3 = C.foo; + var sc4 = C.bar; + } + } + } + } + + class E extends C { + protected z: string; + } \ No newline at end of file diff --git a/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedSubclass.js b/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedSubclass.js new file mode 100644 index 00000000000..255c05ac3ac --- /dev/null +++ b/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedSubclass.js @@ -0,0 +1,99 @@ +//// [protectedClassPropertyAccessibleWithinNestedSubclass.ts] + +class B { + protected x: string; + protected static x: string; +} + +class C extends B { + protected get y() { return this.x; } + protected set y(x) { this.y = this.x; } + protected foo() { return this.x; } + + protected static get y() { return this.x; } + protected static set y(x) { this.y = this.x; } + protected static foo() { return this.x; } + protected static bar() { this.foo(); } + + protected bar() { + class D { + protected foo() { + var c = new C(); + var c1 = c.y; + var c2 = c.x; + var c3 = c.foo; + var c4 = c.bar; + var c5 = c.z; // error + + var sc1 = C.x; + var sc2 = C.y; + var sc3 = C.foo; + var sc4 = C.bar; + } + } + } +} + +class E extends C { + protected z: string; +} + +//// [protectedClassPropertyAccessibleWithinNestedSubclass.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; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var B = (function () { + function B() { + } + return B; +}()); +var C = (function (_super) { + __extends(C, _super); + function C() { + _super.apply(this, arguments); + } + Object.defineProperty(C.prototype, "y", { + get: function () { return this.x; }, + set: function (x) { this.y = this.x; }, + enumerable: true, + configurable: true + }); + C.prototype.foo = function () { return this.x; }; + Object.defineProperty(C, "y", { + get: function () { return this.x; }, + set: function (x) { this.y = this.x; }, + enumerable: true, + configurable: true + }); + C.foo = function () { return this.x; }; + C.bar = function () { this.foo(); }; + C.prototype.bar = function () { + var D = (function () { + function D() { + } + D.prototype.foo = function () { + var c = new C(); + var c1 = c.y; + var c2 = c.x; + var c3 = c.foo; + var c4 = c.bar; + var c5 = c.z; // error + var sc1 = C.x; + var sc2 = C.y; + var sc3 = C.foo; + var sc4 = C.bar; + }; + return D; + }()); + }; + return C; +}(B)); +var E = (function (_super) { + __extends(E, _super); + function E() { + _super.apply(this, arguments); + } + return E; +}(C)); From 1f096bd0806f6a0c7807bf9d19601d6105a4495a Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 17 Feb 2016 18:44:15 -0800 Subject: [PATCH 066/274] Add '!' non-null assertion postfix operator --- src/compiler/checker.ts | 7 +++++++ src/compiler/emitter.ts | 30 ++++++++++++++++++++---------- src/compiler/parser.ts | 9 +++++++++ src/compiler/types.ts | 6 ++++++ src/compiler/utilities.ts | 2 ++ 5 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f3aece5dcdb..7d7290b9031 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6878,6 +6878,7 @@ namespace ts { case SyntaxKind.NewExpression: case SyntaxKind.TypeAssertionExpression: case SyntaxKind.AsExpression: + case SyntaxKind.NonNullExpression: case SyntaxKind.ParenthesizedExpression: case SyntaxKind.PrefixUnaryExpression: case SyntaxKind.DeleteExpression: @@ -10383,6 +10384,10 @@ namespace ts { return targetType; } + function checkNonNullExpression(node: NonNullExpression) { + return getNonNullableType(checkExpression(node.expression)); + } + function getTypeAtPosition(signature: Signature, pos: number): Type { return signature.hasRestParameter ? pos < signature.parameters.length - 1 ? getTypeOfSymbol(signature.parameters[pos]) : getRestTypeOfSignature(signature) : @@ -11555,6 +11560,8 @@ namespace ts { case SyntaxKind.TypeAssertionExpression: case SyntaxKind.AsExpression: return checkAssertion(node); + case SyntaxKind.NonNullExpression: + return checkNonNullExpression(node); case SyntaxKind.DeleteExpression: return checkDeleteExpression(node); case SyntaxKind.VoidExpression: diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index f08082d72c8..d0d908d84b9 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1533,6 +1533,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge case SyntaxKind.JsxSpreadAttribute: case SyntaxKind.JsxExpression: case SyntaxKind.NewExpression: + case SyntaxKind.NonNullExpression: case SyntaxKind.ParenthesizedExpression: case SyntaxKind.PostfixUnaryExpression: case SyntaxKind.PrefixUnaryExpression: @@ -2077,8 +2078,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge function parenthesizeForAccess(expr: Expression): LeftHandSideExpression { // When diagnosing whether the expression needs parentheses, the decision should be based // on the innermost expression in a chain of nested type assertions. - while (expr.kind === SyntaxKind.TypeAssertionExpression || expr.kind === SyntaxKind.AsExpression) { - expr = (expr).expression; + while (expr.kind === SyntaxKind.TypeAssertionExpression || + expr.kind === SyntaxKind.AsExpression || + expr.kind === SyntaxKind.NonNullExpression) { + expr = (expr).expression; } // isLeftHandSideExpression is almost the correct criterion for when it is not necessary @@ -2326,8 +2329,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge } function skipParentheses(node: Expression): Expression { - while (node.kind === SyntaxKind.ParenthesizedExpression || node.kind === SyntaxKind.TypeAssertionExpression || node.kind === SyntaxKind.AsExpression) { - node = (node).expression; + while (node.kind === SyntaxKind.ParenthesizedExpression || + node.kind === SyntaxKind.TypeAssertionExpression || + node.kind === SyntaxKind.AsExpression || + node.kind === SyntaxKind.NonNullExpression) { + node = (node).expression; } return node; } @@ -2501,13 +2507,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge // not the user. If we didn't want them, the emitter would not have put them // there. if (!nodeIsSynthesized(node) && node.parent.kind !== SyntaxKind.ArrowFunction) { - if (node.expression.kind === SyntaxKind.TypeAssertionExpression || node.expression.kind === SyntaxKind.AsExpression) { - let operand = (node.expression).expression; + if (node.expression.kind === SyntaxKind.TypeAssertionExpression || + node.expression.kind === SyntaxKind.AsExpression || + node.expression.kind === SyntaxKind.NonNullExpression) { + let operand = (node.expression).expression; // Make sure we consider all nested cast expressions, e.g.: // (-A).x; - while (operand.kind === SyntaxKind.TypeAssertionExpression || operand.kind === SyntaxKind.AsExpression) { - operand = (operand).expression; + while (operand.kind === SyntaxKind.TypeAssertionExpression || + operand.kind === SyntaxKind.AsExpression || + operand.kind === SyntaxKind.NonNullExpression) { + operand = (operand).expression; } // We have an expression of the form: (SubExpr) @@ -7887,9 +7897,9 @@ const _super = (function (geti, seti) { case SyntaxKind.TaggedTemplateExpression: return emitTaggedTemplateExpression(node); case SyntaxKind.TypeAssertionExpression: - return emit((node).expression); case SyntaxKind.AsExpression: - return emit((node).expression); + case SyntaxKind.NonNullExpression: + return emit((node).expression); case SyntaxKind.ParenthesizedExpression: return emitParenExpression(node); case SyntaxKind.FunctionDeclaration: diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 16ee3eb1627..25b95536947 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -178,6 +178,8 @@ namespace ts { case SyntaxKind.AsExpression: return visitNode(cbNode, (node).expression) || visitNode(cbNode, (node).type); + case SyntaxKind.NonNullExpression: + return visitNode(cbNode, (node).expression); case SyntaxKind.ConditionalExpression: return visitNode(cbNode, (node).condition) || visitNode(cbNode, (node).questionToken) || @@ -3726,6 +3728,13 @@ namespace ts { continue; } + if (parseOptional(SyntaxKind.ExclamationToken)) { + const nonNullExpression = createNode(SyntaxKind.NonNullExpression, expression.pos); + nonNullExpression.expression = expression; + expression = finishNode(nonNullExpression); + continue; + } + // when in the [Decorator] context, we do not parse ElementAccess as it could be part of a ComputedPropertyName if (!inDecoratorContext() && parseOptional(SyntaxKind.OpenBracketToken)) { const indexedAccess = createNode(SyntaxKind.ElementAccessExpression, expression.pos); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index d7abcc02963..af4045cf643 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -240,6 +240,7 @@ namespace ts { OmittedExpression, ExpressionWithTypeArguments, AsExpression, + NonNullExpression, // Misc TemplateSpan, @@ -1017,6 +1018,11 @@ namespace ts { export type AssertionExpression = TypeAssertion | AsExpression; + // @kind(SyntaxKind.NonNullExpression) + export interface NonNullExpression extends LeftHandSideExpression { + expression: Expression; + } + /// A JSX expression of the form ... // @kind(SyntaxKind.JsxElement) export interface JsxElement extends PrimaryExpression { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 5494db5fbd6..50005d5c070 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -968,6 +968,7 @@ namespace ts { case SyntaxKind.TaggedTemplateExpression: case SyntaxKind.AsExpression: case SyntaxKind.TypeAssertionExpression: + case SyntaxKind.NonNullExpression: case SyntaxKind.ParenthesizedExpression: case SyntaxKind.FunctionExpression: case SyntaxKind.ClassExpression: @@ -2394,6 +2395,7 @@ namespace ts { case SyntaxKind.ElementAccessExpression: case SyntaxKind.NewExpression: case SyntaxKind.CallExpression: + case SyntaxKind.NonNullExpression: case SyntaxKind.JsxElement: case SyntaxKind.JsxSelfClosingElement: case SyntaxKind.TaggedTemplateExpression: From 46837fd77d23569cd425f3b10f59e7c4237bf5d6 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 17 Feb 2016 19:03:56 -0800 Subject: [PATCH 067/274] Disallow line breaks between operand and '!' non-null assertion operator --- src/compiler/parser.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 25b95536947..f3a9e5cbf85 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -3728,7 +3728,8 @@ namespace ts { continue; } - if (parseOptional(SyntaxKind.ExclamationToken)) { + if (token === SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak()) { + nextToken(); const nonNullExpression = createNode(SyntaxKind.NonNullExpression, expression.pos); nonNullExpression.expression = expression; expression = finishNode(nonNullExpression); From 54ee0b13b36610710880d5afa1c98c4b5b001d43 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 17 Feb 2016 19:04:25 -0800 Subject: [PATCH 068/274] Accepting new baselines --- .../logicalNotOperatorInvalidOperations.errors.txt | 8 +------- .../reference/logicalNotOperatorInvalidOperations.js | 3 +-- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/tests/baselines/reference/logicalNotOperatorInvalidOperations.errors.txt b/tests/baselines/reference/logicalNotOperatorInvalidOperations.errors.txt index 07262962b08..c7d66e17f9d 100644 --- a/tests/baselines/reference/logicalNotOperatorInvalidOperations.errors.txt +++ b/tests/baselines/reference/logicalNotOperatorInvalidOperations.errors.txt @@ -1,19 +1,13 @@ -tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorInvalidOperations.ts(5,17): error TS1005: ',' expected. -tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorInvalidOperations.ts(5,18): error TS1109: Expression expected. tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorInvalidOperations.ts(8,16): error TS2365: Operator '+' cannot be applied to types 'boolean' and 'number'. tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorInvalidOperations.ts(11,16): error TS1109: Expression expected. -==== tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorInvalidOperations.ts (4 errors) ==== +==== tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorInvalidOperations.ts (2 errors) ==== // Unary operator ! var b: number; // operand before ! var BOOLEAN1 = b!; //expect error - ~ -!!! error TS1005: ',' expected. - ~ -!!! error TS1109: Expression expected. // miss parentheses var BOOLEAN2 = !b + b; diff --git a/tests/baselines/reference/logicalNotOperatorInvalidOperations.js b/tests/baselines/reference/logicalNotOperatorInvalidOperations.js index 7b16f2ef36f..0cb941b0e41 100644 --- a/tests/baselines/reference/logicalNotOperatorInvalidOperations.js +++ b/tests/baselines/reference/logicalNotOperatorInvalidOperations.js @@ -15,8 +15,7 @@ var BOOLEAN3 =!; // Unary operator ! var b; // operand before ! -var BOOLEAN1 = b; -!; //expect error +var BOOLEAN1 = b; //expect error // miss parentheses var BOOLEAN2 = !b + b; // miss an operand From 1e8a7e28d00734578098255705b646269aa52f2e Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 18 Feb 2016 09:13:18 -0800 Subject: [PATCH 069/274] Correct && operator to produce nullable values --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7d7290b9031..6a95162804a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11260,7 +11260,7 @@ namespace ts { case SyntaxKind.InKeyword: return checkInExpression(left, right, leftType, rightType); case SyntaxKind.AmpersandAmpersandToken: - return rightType; + return isNullableType(leftType) ? getNullableType(rightType) : rightType; case SyntaxKind.BarBarToken: return getUnionType([getNonNullableType(leftType), rightType]); case SyntaxKind.EqualsToken: From 50ea0bfc711ff68bee03f954eb86e439ff138d5c Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 19 Feb 2016 09:32:56 -0800 Subject: [PATCH 070/274] Support x == null and x != null in non-null guards. Also, allow == and != in type guards. --- src/compiler/checker.ts | 60 ++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7000ace8aff..874dcb40d5a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7065,17 +7065,54 @@ namespace ts { return strictNullChecks && assumeTrue && getResolvedSymbol(expr) === symbol ? getNonNullableType(type) : type; } - function narrowTypeByEquality(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { - // Check that we have 'typeof ' on the left and string literal on the right - if (expr.left.kind !== SyntaxKind.TypeOfExpression || expr.right.kind !== SyntaxKind.StringLiteral) { + function narrowTypeByBinaryExpression(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { + switch (expr.operatorToken.kind) { + case SyntaxKind.EqualsEqualsToken: + case SyntaxKind.ExclamationEqualsToken: + if (expr.right.kind === SyntaxKind.NullKeyword) { + return narrowTypeByNullCheck(type, expr, assumeTrue); + } + // Fall through + case SyntaxKind.EqualsEqualsEqualsToken: + case SyntaxKind.ExclamationEqualsEqualsToken: + if (expr.left.kind === SyntaxKind.TypeOfExpression && expr.right.kind === SyntaxKind.StringLiteral) { + return narrowTypeByTypeof(type, expr, assumeTrue); + } + break; + case SyntaxKind.AmpersandAmpersandToken: + return narrowTypeByAnd(type, expr, assumeTrue); + case SyntaxKind.BarBarToken: + return narrowTypeByOr(type, expr, assumeTrue); + case SyntaxKind.InstanceOfKeyword: + return narrowTypeByInstanceof(type, expr, assumeTrue); + } + return type; + } + + function narrowTypeByNullCheck(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { + // We have '==' or '!=' operator with 'null' on the right + if (expr.operatorToken.kind === SyntaxKind.ExclamationEqualsToken) { + assumeTrue = !assumeTrue; + } + if (!strictNullChecks || assumeTrue) { return type; } + if (expr.left.kind !== SyntaxKind.Identifier || getResolvedSymbol(expr.left) !== symbol) { + return type; + } + return getNonNullableType(type); + } + + function narrowTypeByTypeof(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { + // We have '==', '!=', '====', or !==' operator with 'typeof xxx' on the left + // and string literal on the right const left = expr.left; const right = expr.right; if (left.expression.kind !== SyntaxKind.Identifier || getResolvedSymbol(left.expression) !== symbol) { return type; } - if (expr.operatorToken.kind === SyntaxKind.ExclamationEqualsEqualsToken) { + if (expr.operatorToken.kind === SyntaxKind.ExclamationEqualsToken || + expr.operatorToken.kind === SyntaxKind.ExclamationEqualsEqualsToken) { assumeTrue = !assumeTrue; } const typeInfo = primitiveTypeInfo[right.text]; @@ -7260,20 +7297,7 @@ namespace ts { case SyntaxKind.ParenthesizedExpression: return narrowType(type, (expr).expression, assumeTrue); case SyntaxKind.BinaryExpression: - const operator = (expr).operatorToken.kind; - if (operator === SyntaxKind.EqualsEqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) { - return narrowTypeByEquality(type, expr, assumeTrue); - } - else if (operator === SyntaxKind.AmpersandAmpersandToken) { - return narrowTypeByAnd(type, expr, assumeTrue); - } - else if (operator === SyntaxKind.BarBarToken) { - return narrowTypeByOr(type, expr, assumeTrue); - } - else if (operator === SyntaxKind.InstanceOfKeyword) { - return narrowTypeByInstanceof(type, expr, assumeTrue); - } - break; + return narrowTypeByBinaryExpression(type, expr, assumeTrue); case SyntaxKind.PrefixUnaryExpression: if ((expr).operator === SyntaxKind.ExclamationToken) { return narrowType(type, (expr).operand, !assumeTrue); From d10017f165ca08417c516e8723a3c3faa9cb3da4 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 19 Feb 2016 09:33:11 -0800 Subject: [PATCH 071/274] Accepting new baselines --- ...FormTypeOfEqualEqualHasNoEffect.errors.txt | 50 +++++++++++ ...dOfFormTypeOfEqualEqualHasNoEffect.symbols | 70 ---------------- ...ardOfFormTypeOfEqualEqualHasNoEffect.types | 82 ------------------- ...OfFormTypeOfNotEqualHasNoEffect.errors.txt | 50 +++++++++++ ...ardOfFormTypeOfNotEqualHasNoEffect.symbols | 70 ---------------- ...GuardOfFormTypeOfNotEqualHasNoEffect.types | 82 ------------------- 6 files changed, 100 insertions(+), 304 deletions(-) create mode 100644 tests/baselines/reference/typeGuardOfFormTypeOfEqualEqualHasNoEffect.errors.txt delete mode 100644 tests/baselines/reference/typeGuardOfFormTypeOfEqualEqualHasNoEffect.symbols delete mode 100644 tests/baselines/reference/typeGuardOfFormTypeOfEqualEqualHasNoEffect.types create mode 100644 tests/baselines/reference/typeGuardOfFormTypeOfNotEqualHasNoEffect.errors.txt delete mode 100644 tests/baselines/reference/typeGuardOfFormTypeOfNotEqualHasNoEffect.symbols delete mode 100644 tests/baselines/reference/typeGuardOfFormTypeOfNotEqualHasNoEffect.types diff --git a/tests/baselines/reference/typeGuardOfFormTypeOfEqualEqualHasNoEffect.errors.txt b/tests/baselines/reference/typeGuardOfFormTypeOfEqualEqualHasNoEffect.errors.txt new file mode 100644 index 00000000000..c76c6e819df --- /dev/null +++ b/tests/baselines/reference/typeGuardOfFormTypeOfEqualEqualHasNoEffect.errors.txt @@ -0,0 +1,50 @@ +tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts(13,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'r1' must be of type 'string', but here has type 'number'. +tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts(20,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'r2' must be of type 'boolean', but here has type 'string'. +tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts(27,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'r3' must be of type 'number', but here has type 'boolean'. +tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts(34,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'r4' must be of type 'C', but here has type 'string'. + + +==== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts (4 errors) ==== + class C { private p: string }; + + var strOrNum: string | number; + var strOrBool: string | boolean; + var numOrBool: number | boolean + var strOrC: string | C; + + // typeof x == s has not effect on typeguard + if (typeof strOrNum == "string") { + var r1 = strOrNum; // string | number + } + else { + var r1 = strOrNum; // string | number + ~~ +!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'r1' must be of type 'string', but here has type 'number'. + } + + if (typeof strOrBool == "boolean") { + var r2 = strOrBool; // string | boolean + } + else { + var r2 = strOrBool; // string | boolean + ~~ +!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'r2' must be of type 'boolean', but here has type 'string'. + } + + if (typeof numOrBool == "number") { + var r3 = numOrBool; // number | boolean + } + else { + var r3 = numOrBool; // number | boolean + ~~ +!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'r3' must be of type 'number', but here has type 'boolean'. + } + + if (typeof strOrC == "Object") { + var r4 = strOrC; // string | C + } + else { + var r4 = strOrC; // string | C + ~~ +!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'r4' must be of type 'C', but here has type 'string'. + } \ No newline at end of file diff --git a/tests/baselines/reference/typeGuardOfFormTypeOfEqualEqualHasNoEffect.symbols b/tests/baselines/reference/typeGuardOfFormTypeOfEqualEqualHasNoEffect.symbols deleted file mode 100644 index 69e0dc78738..00000000000 --- a/tests/baselines/reference/typeGuardOfFormTypeOfEqualEqualHasNoEffect.symbols +++ /dev/null @@ -1,70 +0,0 @@ -=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts === -class C { private p: string }; ->C : Symbol(C, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 0, 0)) ->p : Symbol(p, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 0, 9)) - -var strOrNum: string | number; ->strOrNum : Symbol(strOrNum, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 2, 3)) - -var strOrBool: string | boolean; ->strOrBool : Symbol(strOrBool, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 3, 3)) - -var numOrBool: number | boolean ->numOrBool : Symbol(numOrBool, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 4, 3)) - -var strOrC: string | C; ->strOrC : Symbol(strOrC, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 5, 3)) ->C : Symbol(C, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 0, 0)) - -// typeof x == s has not effect on typeguard -if (typeof strOrNum == "string") { ->strOrNum : Symbol(strOrNum, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 2, 3)) - - var r1 = strOrNum; // string | number ->r1 : Symbol(r1, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 9, 7), Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 12, 7)) ->strOrNum : Symbol(strOrNum, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 2, 3)) -} -else { - var r1 = strOrNum; // string | number ->r1 : Symbol(r1, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 9, 7), Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 12, 7)) ->strOrNum : Symbol(strOrNum, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 2, 3)) -} - -if (typeof strOrBool == "boolean") { ->strOrBool : Symbol(strOrBool, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 3, 3)) - - var r2 = strOrBool; // string | boolean ->r2 : Symbol(r2, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 16, 7), Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 19, 7)) ->strOrBool : Symbol(strOrBool, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 3, 3)) -} -else { - var r2 = strOrBool; // string | boolean ->r2 : Symbol(r2, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 16, 7), Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 19, 7)) ->strOrBool : Symbol(strOrBool, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 3, 3)) -} - -if (typeof numOrBool == "number") { ->numOrBool : Symbol(numOrBool, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 4, 3)) - - var r3 = numOrBool; // number | boolean ->r3 : Symbol(r3, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 23, 7), Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 26, 7)) ->numOrBool : Symbol(numOrBool, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 4, 3)) -} -else { - var r3 = numOrBool; // number | boolean ->r3 : Symbol(r3, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 23, 7), Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 26, 7)) ->numOrBool : Symbol(numOrBool, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 4, 3)) -} - -if (typeof strOrC == "Object") { ->strOrC : Symbol(strOrC, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 5, 3)) - - var r4 = strOrC; // string | C ->r4 : Symbol(r4, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 30, 7), Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 33, 7)) ->strOrC : Symbol(strOrC, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 5, 3)) -} -else { - var r4 = strOrC; // string | C ->r4 : Symbol(r4, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 30, 7), Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 33, 7)) ->strOrC : Symbol(strOrC, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 5, 3)) -} diff --git a/tests/baselines/reference/typeGuardOfFormTypeOfEqualEqualHasNoEffect.types b/tests/baselines/reference/typeGuardOfFormTypeOfEqualEqualHasNoEffect.types deleted file mode 100644 index 4bfc8fe6bf1..00000000000 --- a/tests/baselines/reference/typeGuardOfFormTypeOfEqualEqualHasNoEffect.types +++ /dev/null @@ -1,82 +0,0 @@ -=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts === -class C { private p: string }; ->C : C ->p : string - -var strOrNum: string | number; ->strOrNum : string | number - -var strOrBool: string | boolean; ->strOrBool : string | boolean - -var numOrBool: number | boolean ->numOrBool : number | boolean - -var strOrC: string | C; ->strOrC : string | C ->C : C - -// typeof x == s has not effect on typeguard -if (typeof strOrNum == "string") { ->typeof strOrNum == "string" : boolean ->typeof strOrNum : string ->strOrNum : string | number ->"string" : string - - var r1 = strOrNum; // string | number ->r1 : string | number ->strOrNum : string | number -} -else { - var r1 = strOrNum; // string | number ->r1 : string | number ->strOrNum : string | number -} - -if (typeof strOrBool == "boolean") { ->typeof strOrBool == "boolean" : boolean ->typeof strOrBool : string ->strOrBool : string | boolean ->"boolean" : string - - var r2 = strOrBool; // string | boolean ->r2 : string | boolean ->strOrBool : string | boolean -} -else { - var r2 = strOrBool; // string | boolean ->r2 : string | boolean ->strOrBool : string | boolean -} - -if (typeof numOrBool == "number") { ->typeof numOrBool == "number" : boolean ->typeof numOrBool : string ->numOrBool : number | boolean ->"number" : string - - var r3 = numOrBool; // number | boolean ->r3 : number | boolean ->numOrBool : number | boolean -} -else { - var r3 = numOrBool; // number | boolean ->r3 : number | boolean ->numOrBool : number | boolean -} - -if (typeof strOrC == "Object") { ->typeof strOrC == "Object" : boolean ->typeof strOrC : string ->strOrC : string | C ->"Object" : string - - var r4 = strOrC; // string | C ->r4 : string | C ->strOrC : string | C -} -else { - var r4 = strOrC; // string | C ->r4 : string | C ->strOrC : string | C -} diff --git a/tests/baselines/reference/typeGuardOfFormTypeOfNotEqualHasNoEffect.errors.txt b/tests/baselines/reference/typeGuardOfFormTypeOfNotEqualHasNoEffect.errors.txt new file mode 100644 index 00000000000..3b29f3ecba8 --- /dev/null +++ b/tests/baselines/reference/typeGuardOfFormTypeOfNotEqualHasNoEffect.errors.txt @@ -0,0 +1,50 @@ +tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfNotEqualHasNoEffect.ts(13,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'r1' must be of type 'number', but here has type 'string'. +tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfNotEqualHasNoEffect.ts(20,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'r2' must be of type 'string', but here has type 'boolean'. +tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfNotEqualHasNoEffect.ts(27,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'r3' must be of type 'boolean', but here has type 'number'. +tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfNotEqualHasNoEffect.ts(34,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'r4' must be of type 'string', but here has type 'C'. + + +==== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfNotEqualHasNoEffect.ts (4 errors) ==== + class C { private p: string }; + + var strOrNum: string | number; + var strOrBool: string | boolean; + var numOrBool: number | boolean + var strOrC: string | C; + + // typeof x != s has not effect on typeguard + if (typeof strOrNum != "string") { + var r1 = strOrNum; // string | number + } + else { + var r1 = strOrNum; // string | number + ~~ +!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'r1' must be of type 'number', but here has type 'string'. + } + + if (typeof strOrBool != "boolean") { + var r2 = strOrBool; // string | boolean + } + else { + var r2 = strOrBool; // string | boolean + ~~ +!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'r2' must be of type 'string', but here has type 'boolean'. + } + + if (typeof numOrBool != "number") { + var r3 = numOrBool; // number | boolean + } + else { + var r3 = numOrBool; // number | boolean + ~~ +!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'r3' must be of type 'boolean', but here has type 'number'. + } + + if (typeof strOrC != "Object") { + var r4 = strOrC; // string | C + } + else { + var r4 = strOrC; // string | C + ~~ +!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'r4' must be of type 'string', but here has type 'C'. + } \ No newline at end of file diff --git a/tests/baselines/reference/typeGuardOfFormTypeOfNotEqualHasNoEffect.symbols b/tests/baselines/reference/typeGuardOfFormTypeOfNotEqualHasNoEffect.symbols deleted file mode 100644 index b22f1e313a4..00000000000 --- a/tests/baselines/reference/typeGuardOfFormTypeOfNotEqualHasNoEffect.symbols +++ /dev/null @@ -1,70 +0,0 @@ -=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfNotEqualHasNoEffect.ts === -class C { private p: string }; ->C : Symbol(C, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 0, 0)) ->p : Symbol(p, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 0, 9)) - -var strOrNum: string | number; ->strOrNum : Symbol(strOrNum, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 2, 3)) - -var strOrBool: string | boolean; ->strOrBool : Symbol(strOrBool, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 3, 3)) - -var numOrBool: number | boolean ->numOrBool : Symbol(numOrBool, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 4, 3)) - -var strOrC: string | C; ->strOrC : Symbol(strOrC, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 5, 3)) ->C : Symbol(C, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 0, 0)) - -// typeof x != s has not effect on typeguard -if (typeof strOrNum != "string") { ->strOrNum : Symbol(strOrNum, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 2, 3)) - - var r1 = strOrNum; // string | number ->r1 : Symbol(r1, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 9, 7), Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 12, 7)) ->strOrNum : Symbol(strOrNum, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 2, 3)) -} -else { - var r1 = strOrNum; // string | number ->r1 : Symbol(r1, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 9, 7), Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 12, 7)) ->strOrNum : Symbol(strOrNum, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 2, 3)) -} - -if (typeof strOrBool != "boolean") { ->strOrBool : Symbol(strOrBool, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 3, 3)) - - var r2 = strOrBool; // string | boolean ->r2 : Symbol(r2, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 16, 7), Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 19, 7)) ->strOrBool : Symbol(strOrBool, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 3, 3)) -} -else { - var r2 = strOrBool; // string | boolean ->r2 : Symbol(r2, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 16, 7), Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 19, 7)) ->strOrBool : Symbol(strOrBool, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 3, 3)) -} - -if (typeof numOrBool != "number") { ->numOrBool : Symbol(numOrBool, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 4, 3)) - - var r3 = numOrBool; // number | boolean ->r3 : Symbol(r3, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 23, 7), Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 26, 7)) ->numOrBool : Symbol(numOrBool, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 4, 3)) -} -else { - var r3 = numOrBool; // number | boolean ->r3 : Symbol(r3, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 23, 7), Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 26, 7)) ->numOrBool : Symbol(numOrBool, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 4, 3)) -} - -if (typeof strOrC != "Object") { ->strOrC : Symbol(strOrC, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 5, 3)) - - var r4 = strOrC; // string | C ->r4 : Symbol(r4, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 30, 7), Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 33, 7)) ->strOrC : Symbol(strOrC, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 5, 3)) -} -else { - var r4 = strOrC; // string | C ->r4 : Symbol(r4, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 30, 7), Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 33, 7)) ->strOrC : Symbol(strOrC, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 5, 3)) -} diff --git a/tests/baselines/reference/typeGuardOfFormTypeOfNotEqualHasNoEffect.types b/tests/baselines/reference/typeGuardOfFormTypeOfNotEqualHasNoEffect.types deleted file mode 100644 index 6eabeb25ede..00000000000 --- a/tests/baselines/reference/typeGuardOfFormTypeOfNotEqualHasNoEffect.types +++ /dev/null @@ -1,82 +0,0 @@ -=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfNotEqualHasNoEffect.ts === -class C { private p: string }; ->C : C ->p : string - -var strOrNum: string | number; ->strOrNum : string | number - -var strOrBool: string | boolean; ->strOrBool : string | boolean - -var numOrBool: number | boolean ->numOrBool : number | boolean - -var strOrC: string | C; ->strOrC : string | C ->C : C - -// typeof x != s has not effect on typeguard -if (typeof strOrNum != "string") { ->typeof strOrNum != "string" : boolean ->typeof strOrNum : string ->strOrNum : string | number ->"string" : string - - var r1 = strOrNum; // string | number ->r1 : string | number ->strOrNum : string | number -} -else { - var r1 = strOrNum; // string | number ->r1 : string | number ->strOrNum : string | number -} - -if (typeof strOrBool != "boolean") { ->typeof strOrBool != "boolean" : boolean ->typeof strOrBool : string ->strOrBool : string | boolean ->"boolean" : string - - var r2 = strOrBool; // string | boolean ->r2 : string | boolean ->strOrBool : string | boolean -} -else { - var r2 = strOrBool; // string | boolean ->r2 : string | boolean ->strOrBool : string | boolean -} - -if (typeof numOrBool != "number") { ->typeof numOrBool != "number" : boolean ->typeof numOrBool : string ->numOrBool : number | boolean ->"number" : string - - var r3 = numOrBool; // number | boolean ->r3 : number | boolean ->numOrBool : number | boolean -} -else { - var r3 = numOrBool; // number | boolean ->r3 : number | boolean ->numOrBool : number | boolean -} - -if (typeof strOrC != "Object") { ->typeof strOrC != "Object" : boolean ->typeof strOrC : string ->strOrC : string | C ->"Object" : string - - var r4 = strOrC; // string | C ->r4 : string | C ->strOrC : string | C -} -else { - var r4 = strOrC; // string | C ->r4 : string | C ->strOrC : string | C -} From ed40fbf2d8fbdca5a6407d5ce07df832094643ca Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 19 Feb 2016 16:48:58 -0800 Subject: [PATCH 072/274] Suport both x != null and x != undefined in non-null type guards --- src/compiler/checker.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 874dcb40d5a..eafbff70822 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6986,6 +6986,11 @@ namespace ts { } } + function isNullOrUndefinedLiteral(node: Expression) { + return node.kind === SyntaxKind.NullKeyword || + node.kind === SyntaxKind.Identifier && getResolvedSymbol(node) === undefinedSymbol; + } + // Get the narrowed type of a given symbol at a given location function getNarrowedTypeOfSymbol(symbol: Symbol, node: Node) { let type = getTypeOfSymbol(symbol); @@ -7069,7 +7074,7 @@ namespace ts { switch (expr.operatorToken.kind) { case SyntaxKind.EqualsEqualsToken: case SyntaxKind.ExclamationEqualsToken: - if (expr.right.kind === SyntaxKind.NullKeyword) { + if (isNullOrUndefinedLiteral(expr.right)) { return narrowTypeByNullCheck(type, expr, assumeTrue); } // Fall through From d6485c9c8fd64afd26eafc7cac9a61061970887d Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Mon, 22 Feb 2016 05:37:07 +0800 Subject: [PATCH 073/274] Adds navigation bar items on methods and constructors --- src/services/navigationBar.ts | 23 ++++++++++- ...ionBarItemsInsideMethodsAndConstructors.ts | 38 +++++++++++++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 tests/cases/fourslash/navigationBarItemsInsideMethodsAndConstructors.ts diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index f62c6cb1700..24ca0519859 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -154,6 +154,16 @@ namespace ts.NavigationBar { for (let node of nodes) { switch (node.kind) { case SyntaxKind.ClassDeclaration: + topLevelNodes.push(node); + forEach((node).members, (node) => { + if (node.kind === SyntaxKind.MethodDeclaration || + node.kind === SyntaxKind.Constructor) { + if ((node).body) { + addTopLevelNodes(((node).body).statements, topLevelNodes); + } + } + }); + break; case SyntaxKind.EnumDeclaration: case SyntaxKind.InterfaceDeclaration: topLevelNodes.push(node); @@ -193,6 +203,15 @@ namespace ts.NavigationBar { if (!isFunctionBlock(functionDeclaration.parent)) { return true; } + else { + // Except for parent functions that are methods and constructors. + const grandParentKind = functionDeclaration.parent.parent.kind; + if (grandParentKind === SyntaxKind.MethodDeclaration || + grandParentKind === SyntaxKind.Constructor) { + + return true; + } + } } } @@ -407,7 +426,7 @@ namespace ts.NavigationBar { function createModuleItem(node: ModuleDeclaration): NavigationBarItem { let moduleName = getModuleName(node); - + let childItems = getItemsWorker(getChildNodes((getInnermostModule(node).body).statements), createChildItem); return getNavigationBarItem(moduleName, @@ -422,7 +441,7 @@ namespace ts.NavigationBar { if (node.body && node.body.kind === SyntaxKind.Block) { let childItems = getItemsWorker(sortNodes((node.body).statements), createChildItem); - return getNavigationBarItem(!node.name ? "default": node.name.text , + return getNavigationBarItem(!node.name ? "default": node.name.text, ts.ScriptElementKind.functionElement, getNodeModifiers(node), [getNodeSpan(node)], diff --git a/tests/cases/fourslash/navigationBarItemsInsideMethodsAndConstructors.ts b/tests/cases/fourslash/navigationBarItemsInsideMethodsAndConstructors.ts new file mode 100644 index 00000000000..65e3384e61b --- /dev/null +++ b/tests/cases/fourslash/navigationBarItemsInsideMethodsAndConstructors.ts @@ -0,0 +1,38 @@ +/// + +////class Class { +//// constructor() { +//// {| "itemName": "LocalFunctionInConstructor", "kind": "function", "parentName": "Class"|}function LocalFunctionInConstructor() { +//// +//// } +//// +//// {| "itemName": "LocalInterfaceInConstrcutor", "kind": "interface", "parentName": "foo"|}interface LocalInterfaceInConstrcutor { +//// } +//// +//// enum LocalEnumInConstructor { +//// {| "itemName": "LocalEnumMemberInConstructor", "kind": "property", "parentName": "LocalEnumInConstructor"|}LocalEnumMemberInConstructor, +//// } +//// } +//// method() { +//// {| "itemName": "LocalFunctionInMethod", "kind": "function", "parentName": "foo"|}function LocalFunctionInMethod() { +//// {| "itemName": "LocalFunctionInLocalFunctionInMethod", "kind": "function", "parentName": "bar"|}function LocalFunctionInLocalFunctionInMethod() { +//// +//// } +//// } +//// +//// {| "itemName": "LocalInterfaceInMethod", "kind": "interface", "parentName": "foo"|}interface LocalInterfaceInMethod { +//// } +//// +//// enum LocalEnumInMethod { +//// {| "itemName": "LocalEnumMemberInMethod", "kind": "property", "parentName": "foo"|}LocalEnumMemberInMethod, +//// } +//// } +////} + +test.markers().forEach((marker) => { + verify.getScriptLexicalStructureListContains(marker.data.itemName, marker.data.kind, marker.fileName, marker.data.parentName); +}); + +// no other items +verify.getScriptLexicalStructureListCount(12); + From 1a9dadbc034b651e920d1adb7841a204b2fc0a9e Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Mon, 22 Feb 2016 05:39:19 +0800 Subject: [PATCH 074/274] Fixes typo --- src/services/navigationBar.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index 24ca0519859..ae3e61ba2ca 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -198,13 +198,12 @@ namespace ts.NavigationBar { return true; } - // Or if it is not parented by another function. i.e all functions - // at module scope are 'top level'. + // Or if it is not parented by another function(except for parent functions that + // are methods and constructors). I.e all functions at module scope are 'top level'. if (!isFunctionBlock(functionDeclaration.parent)) { return true; } else { - // Except for parent functions that are methods and constructors. const grandParentKind = functionDeclaration.parent.parent.kind; if (grandParentKind === SyntaxKind.MethodDeclaration || grandParentKind === SyntaxKind.Constructor) { From 1b5b146152329e56e7ba0a298eb2cb77b0660afc Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Mon, 22 Feb 2016 05:42:32 +0800 Subject: [PATCH 075/274] Fixes if statement --- src/services/navigationBar.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index ae3e61ba2ca..62a97699537 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -156,8 +156,7 @@ namespace ts.NavigationBar { case SyntaxKind.ClassDeclaration: topLevelNodes.push(node); forEach((node).members, (node) => { - if (node.kind === SyntaxKind.MethodDeclaration || - node.kind === SyntaxKind.Constructor) { + if (node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.Constructor) { if ((node).body) { addTopLevelNodes(((node).body).statements, topLevelNodes); } From 276885c4cbc08a975b47c159e16b95ebc917a03d Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Sun, 21 Feb 2016 22:03:29 +0000 Subject: [PATCH 076/274] Addressed PR --- src/compiler/checker.ts | 46 +++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5436aba1cd3..91caff0f0cf 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8945,10 +8945,6 @@ namespace ts { } // Property is known to be private or protected at this point - // Get the declaring and enclosing class instance types - const enclosingClassDeclaration = getContainingClass(node); - - const enclosingClass = enclosingClassDeclaration ? getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingClassDeclaration)) : undefined; // Private property is accessible if the property is within the declaring class if (flags & NodeFlags.Private) { @@ -8966,13 +8962,17 @@ namespace ts { if (left.kind === SyntaxKind.SuperKeyword) { return true; } + + // Get the enclosing class that has the declaring class as its base type + const enclosingClass = forEachEnclosingClass(node, enclosingDeclaration => { + const enclosingClass = getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingDeclaration)); + return hasBaseType(enclosingClass, declaringClass) ? enclosingClass : undefined; + }); + // A protected property is accessible if the property is within the declaring class or classes derived from it - const typeClassDeclaration = getClassLikeDeclarationOfSymbol(type.symbol); - if (!enclosingClass || !hasBaseType(enclosingClass, declaringClass)) { - if (!isNodeWithinClass(node, typeClassDeclaration)) { - error(node, Diagnostics.Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses, symbolToString(prop), typeToString(declaringClass)); - return false; - } + if (!enclosingClass) { + error(node, Diagnostics.Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses, symbolToString(prop), typeToString(declaringClass)); + return false; } // No further restrictions for static properties if (flags & NodeFlags.Static) { @@ -8985,11 +8985,9 @@ namespace ts { } // TODO: why is the first part of this check here? - if (getTargetType(type).flags & (TypeFlags.Class | TypeFlags.Interface)) { - if (!(hasBaseType(type, enclosingClass) || isNodeWithinClass(node, typeClassDeclaration))) { - error(node, Diagnostics.Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1, symbolToString(prop), typeToString(enclosingClass)); - return false; - } + if (!(getTargetType(type).flags & (TypeFlags.Class | TypeFlags.Interface) && hasBaseType(type, enclosingClass))) { + error(node, Diagnostics.Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1, symbolToString(prop), typeToString(enclosingClass)); + return false; } return true; } @@ -15467,16 +15465,20 @@ namespace ts { return node.parent && node.parent.kind === SyntaxKind.ExpressionWithTypeArguments; } - function isNodeWithinClass(node: Node, classDeclaration: ClassLikeDeclaration) { + function forEachEnclosingClass(node: Node, callback: (node: Node) => T): T { + let result: T; + while (true) { node = getContainingClass(node); - if (!node) { - return false; - } - if (node === classDeclaration) { - return true; - } + if (!node) break; + if (result = callback(node)) break; } + + return result; + } + + function isNodeWithinClass(node: Node, classDeclaration: ClassLikeDeclaration) { + return !!forEachEnclosingClass(node, n => n === classDeclaration); } function getLeftSideOfImportEqualsOrExportAssignment(nodeOnRightSide: EntityName): ImportEqualsDeclaration | ExportAssignment { From e1be0ff23be90f356d00f59bfe366accd7642daa Mon Sep 17 00:00:00 2001 From: AbubakerB Date: Sun, 21 Feb 2016 22:12:31 +0000 Subject: [PATCH 077/274] Added more tests and accept baselines --- ...AccessibleWithinNestedSubclass1.errors.txt | 180 ++++++++++++ ...PropertyAccessibleWithinNestedSubclass1.js | 260 ++++++++++++++++++ ...PropertyAccessibleWithinNestedSubclass1.ts | 114 ++++++++ 3 files changed, 554 insertions(+) create mode 100644 tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedSubclass1.errors.txt create mode 100644 tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedSubclass1.js create mode 100644 tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts diff --git a/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedSubclass1.errors.txt b/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedSubclass1.errors.txt new file mode 100644 index 00000000000..ee1fbbdaae3 --- /dev/null +++ b/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedSubclass1.errors.txt @@ -0,0 +1,180 @@ +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(15,17): error TS2445: Property 'x' is protected and only accessible within class 'Derived3' and its subclasses. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(32,17): error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived1'. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(34,17): error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived1'. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(35,17): error TS2445: Property 'x' is protected and only accessible within class 'Derived3' and its subclasses. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(36,17): error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived1'. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(52,17): error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived2'. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(53,17): error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived2'. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(55,17): error TS2445: Property 'x' is protected and only accessible within class 'Derived3' and its subclasses. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(73,17): error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived3'. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(74,17): error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived3'. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(75,17): error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived3'. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(77,17): error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived3'. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(93,17): error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived4'. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(94,17): error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived4'. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(95,17): error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived4'. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(96,17): error TS2445: Property 'x' is protected and only accessible within class 'Derived3' and its subclasses. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(110,1): error TS2445: Property 'x' is protected and only accessible within class 'Base' and its subclasses. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(111,1): error TS2445: Property 'x' is protected and only accessible within class 'Base' and its subclasses. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(112,1): error TS2445: Property 'x' is protected and only accessible within class 'Base' and its subclasses. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(113,1): error TS2445: Property 'x' is protected and only accessible within class 'Derived3' and its subclasses. +tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts(114,1): error TS2445: Property 'x' is protected and only accessible within class 'Base' and its subclasses. + + +==== tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts (21 errors) ==== + class Base { + protected x: string; + method() { + class A { + methoda() { + var b: Base; + var d1: Derived1; + var d2: Derived2; + var d3: Derived3; + var d4: Derived4; + + b.x; // OK, accessed within their declaring class + d1.x; // OK, accessed within their declaring class + d2.x; // OK, accessed within their declaring class + d3.x; // Error, redefined in a subclass, can only be accessed in the declaring class or one of its subclasses + ~~~~ +!!! error TS2445: Property 'x' is protected and only accessible within class 'Derived3' and its subclasses. + d4.x; // OK, accessed within their declaring class + } + } + } + } + + class Derived1 extends Base { + method1() { + class B { + method1b() { + var b: Base; + var d1: Derived1; + var d2: Derived2; + var d3: Derived3; + var d4: Derived4; + + b.x; // Error, isn't accessed through an instance of the enclosing class + ~~~ +!!! error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived1'. + d1.x; // OK, accessed within a class derived from their declaring class, and through an instance of the enclosing class + d2.x; // Error, isn't accessed through an instance of the enclosing class + ~~~~ +!!! error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived1'. + d3.x; // Error, redefined in a subclass, can only be accessed in the declaring class or one of its subclasses + ~~~~ +!!! error TS2445: Property 'x' is protected and only accessible within class 'Derived3' and its subclasses. + d4.x; // Error, isn't accessed through an instance of the enclosing class + ~~~~ +!!! error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived1'. + } + } + } + } + + class Derived2 extends Base { + method2() { + class C { + method2c() { + var b: Base; + var d1: Derived1; + var d2: Derived2; + var d3: Derived3; + var d4: Derived4; + + b.x; // Error, isn't accessed through an instance of the enclosing class + ~~~ +!!! error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived2'. + d1.x; // Error, isn't accessed through an instance of the enclosing class + ~~~~ +!!! error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived2'. + d2.x; // OK, accessed within a class derived from their declaring class, and through an instance of the enclosing class + d3.x; // Error, redefined in a subclass, can only be accessed in the declaring class or one of its subclasses + ~~~~ +!!! error TS2445: Property 'x' is protected and only accessible within class 'Derived3' and its subclasses. + d4.x; // OK, accessed within a class derived from their declaring class, and through an instance of the enclosing class or one of its subclasses + } + } + } + } + + class Derived3 extends Derived1 { + protected x: string; + method3() { + class D { + method3d() { + var b: Base; + var d1: Derived1; + var d2: Derived2; + var d3: Derived3; + var d4: Derived4; + + b.x; // Error, isn't accessed through an instance of the enclosing class + ~~~ +!!! error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived3'. + d1.x; // Error, isn't accessed through an instance of the enclosing class + ~~~~ +!!! error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived3'. + d2.x; // Error, isn't accessed through an instance of the enclosing class + ~~~~ +!!! error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived3'. + d3.x; // OK, accessed within their declaring class + d4.x; // Error, isn't accessed through an instance of the enclosing class + ~~~~ +!!! error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived3'. + } + } + } + } + + class Derived4 extends Derived2 { + method4() { + class E { + method4e() { + var b: Base; + var d1: Derived1; + var d2: Derived2; + var d3: Derived3; + var d4: Derived4; + + b.x; // Error, isn't accessed through an instance of the enclosing class + ~~~ +!!! error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived4'. + d1.x; // Error, isn't accessed through an instance of the enclosing class + ~~~~ +!!! error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived4'. + d2.x; // Error, isn't accessed through an instance of the enclosing class + ~~~~ +!!! error TS2446: Property 'x' is protected and only accessible through an instance of class 'Derived4'. + d3.x; // Error, redefined in a subclass, can only be accessed in the declaring class or one of its subclasses + ~~~~ +!!! error TS2445: Property 'x' is protected and only accessible within class 'Derived3' and its subclasses. + d4.x; // OK, accessed within a class derived from their declaring class, and through an instance of the enclosing class + } + } + } + } + + + var b: Base; + var d1: Derived1; + var d2: Derived2; + var d3: Derived3; + var d4: Derived4; + + b.x; // Error, neither within their declaring class nor classes derived from their declaring class + ~~~ +!!! error TS2445: Property 'x' is protected and only accessible within class 'Base' and its subclasses. + d1.x; // Error, neither within their declaring class nor classes derived from their declaring class + ~~~~ +!!! error TS2445: Property 'x' is protected and only accessible within class 'Base' and its subclasses. + d2.x; // Error, neither within their declaring class nor classes derived from their declaring class + ~~~~ +!!! error TS2445: Property 'x' is protected and only accessible within class 'Base' and its subclasses. + d3.x; // Error, neither within their declaring class nor classes derived from their declaring class + ~~~~ +!!! error TS2445: Property 'x' is protected and only accessible within class 'Derived3' and its subclasses. + d4.x; // Error, neither within their declaring class nor classes derived from their declaring class + ~~~~ +!!! error TS2445: Property 'x' is protected and only accessible within class 'Base' and its subclasses. \ No newline at end of file diff --git a/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedSubclass1.js b/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedSubclass1.js new file mode 100644 index 00000000000..02ad29bd312 --- /dev/null +++ b/tests/baselines/reference/protectedClassPropertyAccessibleWithinNestedSubclass1.js @@ -0,0 +1,260 @@ +//// [protectedClassPropertyAccessibleWithinNestedSubclass1.ts] +class Base { + protected x: string; + method() { + class A { + methoda() { + var b: Base; + var d1: Derived1; + var d2: Derived2; + var d3: Derived3; + var d4: Derived4; + + b.x; // OK, accessed within their declaring class + d1.x; // OK, accessed within their declaring class + d2.x; // OK, accessed within their declaring class + d3.x; // Error, redefined in a subclass, can only be accessed in the declaring class or one of its subclasses + d4.x; // OK, accessed within their declaring class + } + } + } +} + +class Derived1 extends Base { + method1() { + class B { + method1b() { + var b: Base; + var d1: Derived1; + var d2: Derived2; + var d3: Derived3; + var d4: Derived4; + + b.x; // Error, isn't accessed through an instance of the enclosing class + d1.x; // OK, accessed within a class derived from their declaring class, and through an instance of the enclosing class + d2.x; // Error, isn't accessed through an instance of the enclosing class + d3.x; // Error, redefined in a subclass, can only be accessed in the declaring class or one of its subclasses + d4.x; // Error, isn't accessed through an instance of the enclosing class + } + } + } +} + +class Derived2 extends Base { + method2() { + class C { + method2c() { + var b: Base; + var d1: Derived1; + var d2: Derived2; + var d3: Derived3; + var d4: Derived4; + + b.x; // Error, isn't accessed through an instance of the enclosing class + d1.x; // Error, isn't accessed through an instance of the enclosing class + d2.x; // OK, accessed within a class derived from their declaring class, and through an instance of the enclosing class + d3.x; // Error, redefined in a subclass, can only be accessed in the declaring class or one of its subclasses + d4.x; // OK, accessed within a class derived from their declaring class, and through an instance of the enclosing class or one of its subclasses + } + } + } +} + +class Derived3 extends Derived1 { + protected x: string; + method3() { + class D { + method3d() { + var b: Base; + var d1: Derived1; + var d2: Derived2; + var d3: Derived3; + var d4: Derived4; + + b.x; // Error, isn't accessed through an instance of the enclosing class + d1.x; // Error, isn't accessed through an instance of the enclosing class + d2.x; // Error, isn't accessed through an instance of the enclosing class + d3.x; // OK, accessed within their declaring class + d4.x; // Error, isn't accessed through an instance of the enclosing class + } + } + } +} + +class Derived4 extends Derived2 { + method4() { + class E { + method4e() { + var b: Base; + var d1: Derived1; + var d2: Derived2; + var d3: Derived3; + var d4: Derived4; + + b.x; // Error, isn't accessed through an instance of the enclosing class + d1.x; // Error, isn't accessed through an instance of the enclosing class + d2.x; // Error, isn't accessed through an instance of the enclosing class + d3.x; // Error, redefined in a subclass, can only be accessed in the declaring class or one of its subclasses + d4.x; // OK, accessed within a class derived from their declaring class, and through an instance of the enclosing class + } + } + } +} + + +var b: Base; +var d1: Derived1; +var d2: Derived2; +var d3: Derived3; +var d4: Derived4; + +b.x; // Error, neither within their declaring class nor classes derived from their declaring class +d1.x; // Error, neither within their declaring class nor classes derived from their declaring class +d2.x; // Error, neither within their declaring class nor classes derived from their declaring class +d3.x; // Error, neither within their declaring class nor classes derived from their declaring class +d4.x; // Error, neither within their declaring class nor classes derived from their declaring class + +//// [protectedClassPropertyAccessibleWithinNestedSubclass1.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; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var Base = (function () { + function Base() { + } + Base.prototype.method = function () { + var A = (function () { + function A() { + } + A.prototype.methoda = function () { + var b; + var d1; + var d2; + var d3; + var d4; + b.x; // OK, accessed within their declaring class + d1.x; // OK, accessed within their declaring class + d2.x; // OK, accessed within their declaring class + d3.x; // Error, redefined in a subclass, can only be accessed in the declaring class or one of its subclasses + d4.x; // OK, accessed within their declaring class + }; + return A; + }()); + }; + return Base; +}()); +var Derived1 = (function (_super) { + __extends(Derived1, _super); + function Derived1() { + _super.apply(this, arguments); + } + Derived1.prototype.method1 = function () { + var B = (function () { + function B() { + } + B.prototype.method1b = function () { + var b; + var d1; + var d2; + var d3; + var d4; + b.x; // Error, isn't accessed through an instance of the enclosing class + d1.x; // OK, accessed within a class derived from their declaring class, and through an instance of the enclosing class + d2.x; // Error, isn't accessed through an instance of the enclosing class + d3.x; // Error, redefined in a subclass, can only be accessed in the declaring class or one of its subclasses + d4.x; // Error, isn't accessed through an instance of the enclosing class + }; + return B; + }()); + }; + return Derived1; +}(Base)); +var Derived2 = (function (_super) { + __extends(Derived2, _super); + function Derived2() { + _super.apply(this, arguments); + } + Derived2.prototype.method2 = function () { + var C = (function () { + function C() { + } + C.prototype.method2c = function () { + var b; + var d1; + var d2; + var d3; + var d4; + b.x; // Error, isn't accessed through an instance of the enclosing class + d1.x; // Error, isn't accessed through an instance of the enclosing class + d2.x; // OK, accessed within a class derived from their declaring class, and through an instance of the enclosing class + d3.x; // Error, redefined in a subclass, can only be accessed in the declaring class or one of its subclasses + d4.x; // OK, accessed within a class derived from their declaring class, and through an instance of the enclosing class or one of its subclasses + }; + return C; + }()); + }; + return Derived2; +}(Base)); +var Derived3 = (function (_super) { + __extends(Derived3, _super); + function Derived3() { + _super.apply(this, arguments); + } + Derived3.prototype.method3 = function () { + var D = (function () { + function D() { + } + D.prototype.method3d = function () { + var b; + var d1; + var d2; + var d3; + var d4; + b.x; // Error, isn't accessed through an instance of the enclosing class + d1.x; // Error, isn't accessed through an instance of the enclosing class + d2.x; // Error, isn't accessed through an instance of the enclosing class + d3.x; // OK, accessed within their declaring class + d4.x; // Error, isn't accessed through an instance of the enclosing class + }; + return D; + }()); + }; + return Derived3; +}(Derived1)); +var Derived4 = (function (_super) { + __extends(Derived4, _super); + function Derived4() { + _super.apply(this, arguments); + } + Derived4.prototype.method4 = function () { + var E = (function () { + function E() { + } + E.prototype.method4e = function () { + var b; + var d1; + var d2; + var d3; + var d4; + b.x; // Error, isn't accessed through an instance of the enclosing class + d1.x; // Error, isn't accessed through an instance of the enclosing class + d2.x; // Error, isn't accessed through an instance of the enclosing class + d3.x; // Error, redefined in a subclass, can only be accessed in the declaring class or one of its subclasses + d4.x; // OK, accessed within a class derived from their declaring class, and through an instance of the enclosing class + }; + return E; + }()); + }; + return Derived4; +}(Derived2)); +var b; +var d1; +var d2; +var d3; +var d4; +b.x; // Error, neither within their declaring class nor classes derived from their declaring class +d1.x; // Error, neither within their declaring class nor classes derived from their declaring class +d2.x; // Error, neither within their declaring class nor classes derived from their declaring class +d3.x; // Error, neither within their declaring class nor classes derived from their declaring class +d4.x; // Error, neither within their declaring class nor classes derived from their declaring class diff --git a/tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts b/tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts new file mode 100644 index 00000000000..1128da70795 --- /dev/null +++ b/tests/cases/conformance/classes/members/accessibility/protectedClassPropertyAccessibleWithinNestedSubclass1.ts @@ -0,0 +1,114 @@ +class Base { + protected x: string; + method() { + class A { + methoda() { + var b: Base; + var d1: Derived1; + var d2: Derived2; + var d3: Derived3; + var d4: Derived4; + + b.x; // OK, accessed within their declaring class + d1.x; // OK, accessed within their declaring class + d2.x; // OK, accessed within their declaring class + d3.x; // Error, redefined in a subclass, can only be accessed in the declaring class or one of its subclasses + d4.x; // OK, accessed within their declaring class + } + } + } +} + +class Derived1 extends Base { + method1() { + class B { + method1b() { + var b: Base; + var d1: Derived1; + var d2: Derived2; + var d3: Derived3; + var d4: Derived4; + + b.x; // Error, isn't accessed through an instance of the enclosing class + d1.x; // OK, accessed within a class derived from their declaring class, and through an instance of the enclosing class + d2.x; // Error, isn't accessed through an instance of the enclosing class + d3.x; // Error, redefined in a subclass, can only be accessed in the declaring class or one of its subclasses + d4.x; // Error, isn't accessed through an instance of the enclosing class + } + } + } +} + +class Derived2 extends Base { + method2() { + class C { + method2c() { + var b: Base; + var d1: Derived1; + var d2: Derived2; + var d3: Derived3; + var d4: Derived4; + + b.x; // Error, isn't accessed through an instance of the enclosing class + d1.x; // Error, isn't accessed through an instance of the enclosing class + d2.x; // OK, accessed within a class derived from their declaring class, and through an instance of the enclosing class + d3.x; // Error, redefined in a subclass, can only be accessed in the declaring class or one of its subclasses + d4.x; // OK, accessed within a class derived from their declaring class, and through an instance of the enclosing class or one of its subclasses + } + } + } +} + +class Derived3 extends Derived1 { + protected x: string; + method3() { + class D { + method3d() { + var b: Base; + var d1: Derived1; + var d2: Derived2; + var d3: Derived3; + var d4: Derived4; + + b.x; // Error, isn't accessed through an instance of the enclosing class + d1.x; // Error, isn't accessed through an instance of the enclosing class + d2.x; // Error, isn't accessed through an instance of the enclosing class + d3.x; // OK, accessed within their declaring class + d4.x; // Error, isn't accessed through an instance of the enclosing class + } + } + } +} + +class Derived4 extends Derived2 { + method4() { + class E { + method4e() { + var b: Base; + var d1: Derived1; + var d2: Derived2; + var d3: Derived3; + var d4: Derived4; + + b.x; // Error, isn't accessed through an instance of the enclosing class + d1.x; // Error, isn't accessed through an instance of the enclosing class + d2.x; // Error, isn't accessed through an instance of the enclosing class + d3.x; // Error, redefined in a subclass, can only be accessed in the declaring class or one of its subclasses + d4.x; // OK, accessed within a class derived from their declaring class, and through an instance of the enclosing class + } + } + } +} + + +var b: Base; +var d1: Derived1; +var d2: Derived2; +var d3: Derived3; +var d4: Derived4; + +b.x; // Error, neither within their declaring class nor classes derived from their declaring class +d1.x; // Error, neither within their declaring class nor classes derived from their declaring class +d2.x; // Error, neither within their declaring class nor classes derived from their declaring class +d3.x; // Error, neither within their declaring class nor classes derived from their declaring class +d4.x; // Error, neither within their declaring class nor classes derived from their declaring class \ No newline at end of file From 4d933f86ce190b1add76d54474700ed5c78863e7 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Mon, 22 Feb 2016 11:19:38 +0800 Subject: [PATCH 078/274] Fixes method and constructor top-level --- src/services/navigationBar.ts | 30 +++++++++++++++++++ ...ionBarItemsInsideMethodsAndConstructors.ts | 1 - 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index 62a97699537..44a71141694 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -158,6 +158,7 @@ namespace ts.NavigationBar { forEach((node).members, (node) => { if (node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.Constructor) { if ((node).body) { + topLevelNodes.push(node); addTopLevelNodes(((node).body).statements, topLevelNodes); } } @@ -386,6 +387,10 @@ namespace ts.NavigationBar { case SyntaxKind.ClassDeclaration: return createClassItem(node); + + case SyntaxKind.MethodDeclaration: + case SyntaxKind.Constructor: + return createMemberFunctionLikeItem(node); case SyntaxKind.EnumDeclaration: return createEnumItem(node); @@ -449,6 +454,31 @@ namespace ts.NavigationBar { return undefined; } + + function createMemberFunctionLikeItem(node: MethodDeclaration | ConstructorDeclaration) { + if (node.body && node.body.kind === SyntaxKind.Block) { + let childItems = getItemsWorker(sortNodes((node.body).statements), createChildItem); + let scriptElementKind: string; + let memberFunctionName: string; + if (node.kind === SyntaxKind.MethodDeclaration) { + memberFunctionName = getPropertyNameForPropertyNameNode(node.name); + scriptElementKind = ts.ScriptElementKind.memberFunctionElement; + } + else { + memberFunctionName = "constructor"; + scriptElementKind = ts.ScriptElementKind.constructorImplementationElement; + } + + return getNavigationBarItem(memberFunctionName, + scriptElementKind, + getNodeModifiers(node), + [getNodeSpan(node)], + childItems, + getIndent(node)); + } + + return undefined; + } function createSourceFileItem(node: SourceFile): ts.NavigationBarItem { let childItems = getItemsWorker(getChildNodes(node.statements), createChildItem); diff --git a/tests/cases/fourslash/navigationBarItemsInsideMethodsAndConstructors.ts b/tests/cases/fourslash/navigationBarItemsInsideMethodsAndConstructors.ts index 65e3384e61b..538e864d10c 100644 --- a/tests/cases/fourslash/navigationBarItemsInsideMethodsAndConstructors.ts +++ b/tests/cases/fourslash/navigationBarItemsInsideMethodsAndConstructors.ts @@ -35,4 +35,3 @@ test.markers().forEach((marker) => { // no other items verify.getScriptLexicalStructureListCount(12); - From fd2d28df0261b6b574cc415e9d47b02df21371eb Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Mon, 22 Feb 2016 12:38:14 +0800 Subject: [PATCH 079/274] Fixes new implementation --- src/services/navigationBar.ts | 23 +++++++++++++------ ...ionBarItemsInsideMethodsAndConstructors.ts | 7 +++++- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index 44a71141694..b537a56e856 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -157,8 +157,12 @@ namespace ts.NavigationBar { topLevelNodes.push(node); forEach((node).members, (node) => { if (node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.Constructor) { - if ((node).body) { - topLevelNodes.push(node); + type FunctionLikeMember = MethodDeclaration | ConstructorDeclaration; + if ((node).body) { + // We do not include methods that does not have child functions in it, because of duplications. + if (hasNonAnonymousFunctionDeclarations(((node).body).statements)) { + topLevelNodes.push(node); + } addTopLevelNodes(((node).body).statements, topLevelNodes); } } @@ -186,14 +190,19 @@ namespace ts.NavigationBar { } } + function hasNonAnonymousFunctionDeclarations(nodes: NodeArray) { + if (forEach(nodes, s => s.kind === SyntaxKind.FunctionDeclaration && !isEmpty((s).name.text))) { + return true; + } + } + function isTopLevelFunctionDeclaration(functionDeclaration: FunctionLikeDeclaration) { if (functionDeclaration.kind === SyntaxKind.FunctionDeclaration) { // A function declaration is 'top level' if it contains any function declarations // within it. if (functionDeclaration.body && functionDeclaration.body.kind === SyntaxKind.Block) { // Proper function declarations can only have identifier names - if (forEach((functionDeclaration.body).statements, - s => s.kind === SyntaxKind.FunctionDeclaration && !isEmpty((s).name.text))) { + if (hasNonAnonymousFunctionDeclarations((functionDeclaration.body).statements)) { return true; } @@ -390,13 +399,13 @@ namespace ts.NavigationBar { case SyntaxKind.MethodDeclaration: case SyntaxKind.Constructor: - return createMemberFunctionLikeItem(node); + return createMemberFunctionLikeItem(node); case SyntaxKind.EnumDeclaration: return createEnumItem(node); case SyntaxKind.InterfaceDeclaration: - return createIterfaceItem(node); + return createInterfaceItem(node); case SyntaxKind.ModuleDeclaration: return createModuleItem(node); @@ -540,7 +549,7 @@ namespace ts.NavigationBar { getIndent(node)); } - function createIterfaceItem(node: InterfaceDeclaration): ts.NavigationBarItem { + function createInterfaceItem(node: InterfaceDeclaration): ts.NavigationBarItem { let childItems = getItemsWorker(sortNodes(removeDynamicallyNamedProperties(node)), createChildItem); return getNavigationBarItem( node.name.text, diff --git a/tests/cases/fourslash/navigationBarItemsInsideMethodsAndConstructors.ts b/tests/cases/fourslash/navigationBarItemsInsideMethodsAndConstructors.ts index 538e864d10c..4dcca43af35 100644 --- a/tests/cases/fourslash/navigationBarItemsInsideMethodsAndConstructors.ts +++ b/tests/cases/fourslash/navigationBarItemsInsideMethodsAndConstructors.ts @@ -13,6 +13,7 @@ //// {| "itemName": "LocalEnumMemberInConstructor", "kind": "property", "parentName": "LocalEnumInConstructor"|}LocalEnumMemberInConstructor, //// } //// } +//// //// method() { //// {| "itemName": "LocalFunctionInMethod", "kind": "function", "parentName": "foo"|}function LocalFunctionInMethod() { //// {| "itemName": "LocalFunctionInLocalFunctionInMethod", "kind": "function", "parentName": "bar"|}function LocalFunctionInLocalFunctionInMethod() { @@ -27,6 +28,10 @@ //// {| "itemName": "LocalEnumMemberInMethod", "kind": "property", "parentName": "foo"|}LocalEnumMemberInMethod, //// } //// } +//// +//// emptyMethod() { // Non child functions method should not be duplicated +//// +//// } ////} test.markers().forEach((marker) => { @@ -34,4 +39,4 @@ test.markers().forEach((marker) => { }); // no other items -verify.getScriptLexicalStructureListCount(12); +verify.getScriptLexicalStructureListCount(17); From 3d7631dbe86b5b500c6218588df0833932ca809a Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 27 Feb 2016 11:39:16 -0800 Subject: [PATCH 080/274] Support dotted names ("x.y.z") in type guards --- src/compiler/checker.ts | 323 +++++++++++++++++++++++----------------- src/compiler/types.ts | 4 +- 2 files changed, 191 insertions(+), 136 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a2b8b5a2a7a..cd4a21204a2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -69,10 +69,7 @@ namespace ts { isUnknownSymbol: symbol => symbol === unknownSymbol, getDiagnostics, getGlobalDiagnostics, - - // The language service will always care about the narrowed type of a symbol, because that is - // the type the language says the symbol should have. - getTypeOfSymbolAtLocation: getNarrowedTypeOfSymbol, + getTypeOfSymbolAtLocation, getSymbolsOfParameterPropertyDeclaration, getDeclaredTypeOfSymbol, getPropertiesOfType, @@ -6869,7 +6866,7 @@ namespace ts { function getResolvedSymbol(node: Identifier): Symbol { const links = getNodeLinks(node); if (!links.resolvedSymbol) { - links.resolvedSymbol = (!nodeIsMissing(node) && resolveName(node, node.text, SymbolFlags.Value | SymbolFlags.ExportValue, Diagnostics.Cannot_find_name_0, node)) || unknownSymbol; + links.resolvedSymbol = !nodeIsMissing(node) && resolveName(node, node.text, SymbolFlags.Value | SymbolFlags.ExportValue, Diagnostics.Cannot_find_name_0, node) || unknownSymbol; } return links.resolvedSymbol; } @@ -6893,48 +6890,59 @@ namespace ts { Debug.fail("should not get here"); } + // Return the assignment key for a "dotted name" (i.e. a sequence of identifiers + // separated by dots). The key consists of the id of the symbol referenced by the + // leftmost identifier followed by zero or more property names separated by dots. + // The result is undefined if the reference isn't a dotted name. + function getAssignmentKey(node: Node): string { + if (node.kind === SyntaxKind.Identifier) { + const symbol = getResolvedSymbol(node); + return symbol !== unknownSymbol ? "" + getSymbolId(symbol) : undefined; + } + if (node.kind === SyntaxKind.PropertyAccessExpression) { + const key = getAssignmentKey((node).expression); + return key && key + "." + (node).name.text; + } + return undefined; + } + function hasInitializer(node: VariableLikeDeclaration): boolean { return !!(node.initializer || isBindingPattern(node.parent) && hasInitializer(node.parent.parent)); } - // Check if a given variable is assigned within a given syntax node - function isVariableAssignedWithin(symbol: Symbol, node: Node): boolean { - const links = getNodeLinks(node); - if (links.assignmentChecks) { - const cachedResult = links.assignmentChecks[symbol.id]; - if (cachedResult !== undefined) { - return cachedResult; - } - } - else { - links.assignmentChecks = {}; - } - return links.assignmentChecks[symbol.id] = isAssignedIn(node); + // For a given node compute a map of which dotted names are assigned within + // the node. + function getAssignmentMap(node: Node): Map { + const assignmentMap: Map = {}; + visit(node); + return assignmentMap; - function isAssignedInBinaryExpression(node: BinaryExpression) { + function visitBinaryExpression(node: BinaryExpression) { if (node.operatorToken.kind >= SyntaxKind.FirstAssignment && node.operatorToken.kind <= SyntaxKind.LastAssignment) { - const n = skipParenthesizedNodes(node.left); - if (n.kind === SyntaxKind.Identifier && getResolvedSymbol(n) === symbol) { - return true; + const key = getAssignmentKey(skipParenthesizedNodes(node.left)); + if (key) { + assignmentMap[key] = true; } } - return forEachChild(node, isAssignedIn); + forEachChild(node, visit); } - function isAssignedInVariableDeclaration(node: VariableLikeDeclaration) { - if (!isBindingPattern(node.name) && getSymbolOfNode(node) === symbol && hasInitializer(node)) { - return true; + function visitVariableDeclaration(node: VariableLikeDeclaration) { + if (!isBindingPattern(node.name) && hasInitializer(node)) { + assignmentMap[getSymbolId(getSymbolOfNode(node))] = true; } - return forEachChild(node, isAssignedIn); + forEachChild(node, visit); } - function isAssignedIn(node: Node): boolean { + function visit(node: Node) { switch (node.kind) { case SyntaxKind.BinaryExpression: - return isAssignedInBinaryExpression(node); + visitBinaryExpression(node); + break; case SyntaxKind.VariableDeclaration: case SyntaxKind.BindingElement: - return isAssignedInVariableDeclaration(node); + visitVariableDeclaration(node); + break; case SyntaxKind.ObjectBindingPattern: case SyntaxKind.ArrayBindingPattern: case SyntaxKind.ArrayLiteralExpression: @@ -6980,9 +6988,30 @@ namespace ts { case SyntaxKind.JsxSpreadAttribute: case SyntaxKind.JsxOpeningElement: case SyntaxKind.JsxExpression: - return forEachChild(node, isAssignedIn); + forEachChild(node, visit); + break; } - return false; + } + } + + function isReferenceAssignedWithin(reference: Node, node: Node): boolean { + const key = getAssignmentKey(reference); + if (key) { + const links = getNodeLinks(node); + return (links.assignmentMap || (links.assignmentMap = getAssignmentMap(node)))[key]; + } + return false; + } + + function isAnyPartOfReferenceAssignedWithin(reference: Node, node: Node) { + while (true) { + if (isReferenceAssignedWithin(reference, node)) { + return true; + } + if (reference.kind !== SyntaxKind.PropertyAccessExpression) { + return false; + } + reference = (reference).expression; } } @@ -6991,83 +7020,112 @@ namespace ts { node.kind === SyntaxKind.Identifier && getResolvedSymbol(node) === undefinedSymbol; } - // Get the narrowed type of a given symbol at a given location - function getNarrowedTypeOfSymbol(symbol: Symbol, node: Node) { - let type = getTypeOfSymbol(symbol); - // Only narrow when symbol is variable of type any or an object, union, or type parameter type - if (node && symbol.flags & SymbolFlags.Variable) { - if (isTypeAny(type) || type.flags & (TypeFlags.ObjectType | TypeFlags.Union | TypeFlags.TypeParameter)) { - const declaration = getDeclarationOfKind(symbol, SyntaxKind.VariableDeclaration); - const top = declaration && getDeclarationContainer(declaration); - const originalType = type; - const nodeStack: {node: Node, child: Node}[] = []; - loop: while (node.parent) { - const child = node; - node = node.parent; - switch (node.kind) { - case SyntaxKind.IfStatement: - case SyntaxKind.ConditionalExpression: - case SyntaxKind.BinaryExpression: - nodeStack.push({node, child}); - break; - case SyntaxKind.SourceFile: - case SyntaxKind.ModuleDeclaration: - // Stop at the first containing file or module declaration - break loop; - } - if (node === top) { - break; - } - } + function getLeftmostIdentifier(node: Node): Identifier { + switch (node.kind) { + case SyntaxKind.Identifier: + return node; + case SyntaxKind.PropertyAccessExpression: + return getLeftmostIdentifier((node).expression); + } + return undefined; + } - let nodes: {node: Node, child: Node}; - while (nodes = nodeStack.pop()) { - const {node, child} = nodes; - switch (node.kind) { - case SyntaxKind.IfStatement: - // In a branch of an if statement, narrow based on controlling expression - if (child !== (node).expression) { - type = narrowType(type, (node).expression, /*assumeTrue*/ child === (node).thenStatement); - } - break; - case SyntaxKind.ConditionalExpression: - // In a branch of a conditional expression, narrow based on controlling condition - if (child !== (node).condition) { - type = narrowType(type, (node).condition, /*assumeTrue*/ child === (node).whenTrue); - } - break; - case SyntaxKind.BinaryExpression: - // In the right operand of an && or ||, narrow based on left operand - if (child === (node).right) { - if ((node).operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) { - type = narrowType(type, (node).left, /*assumeTrue*/ true); - } - else if ((node).operatorToken.kind === SyntaxKind.BarBarToken) { - type = narrowType(type, (node).left, /*assumeTrue*/ false); - } - } - break; - default: - Debug.fail("Unreachable!"); - } - - // Use original type if construct contains assignments to variable - if (type !== originalType && isVariableAssignedWithin(symbol, node)) { - type = originalType; - } - } - - // Preserve old top-level behavior - if the branch is really an empty set, revert to prior type - if (type === emptyUnionType) { - type = originalType; - } + function isMatchingReference(source: Node, target: Node): boolean { + if (source.kind === target.kind) { + if (source.kind === SyntaxKind.Identifier) { + return getResolvedSymbol(source) === getResolvedSymbol(target); } + if (source.kind === SyntaxKind.PropertyAccessExpression) { + return (source).name.text === (target).name.text && + isMatchingReference((source).expression, (target).expression); + } + } + return false; + } + + // Get the narrowed type of a given symbol at a given location + function getNarrowedTypeOfReference(type: Type, reference: IdentifierOrPropertyAccess) { + if (!(type.flags & (TypeFlags.Any | TypeFlags.ObjectType | TypeFlags.Union | TypeFlags.TypeParameter))) { + return type; + } + const leftmostIdentifier = getLeftmostIdentifier(reference); + if (!leftmostIdentifier) { + return type; + } + const leftmostSymbol = getResolvedSymbol(leftmostIdentifier); + if (!(leftmostSymbol.flags & SymbolFlags.Variable)) { + return type; + } + const declaration = getDeclarationOfKind(leftmostSymbol, SyntaxKind.VariableDeclaration); + const top = declaration && getDeclarationContainer(declaration); + const originalType = type; + const nodeStack: { node: Node, child: Node }[] = []; + let node: Node = reference; + loop: while (node.parent) { + const child = node; + node = node.parent; + switch (node.kind) { + case SyntaxKind.IfStatement: + case SyntaxKind.ConditionalExpression: + case SyntaxKind.BinaryExpression: + nodeStack.push({node, child}); + break; + case SyntaxKind.SourceFile: + case SyntaxKind.ModuleDeclaration: + // Stop at the first containing file or module declaration + break loop; + } + if (node === top) { + break; + } + } + + let nodes: { node: Node, child: Node }; + while (nodes = nodeStack.pop()) { + const {node, child} = nodes; + switch (node.kind) { + case SyntaxKind.IfStatement: + // In a branch of an if statement, narrow based on controlling expression + if (child !== (node).expression) { + type = narrowType(type, (node).expression, /*assumeTrue*/ child === (node).thenStatement); + } + break; + case SyntaxKind.ConditionalExpression: + // In a branch of a conditional expression, narrow based on controlling condition + if (child !== (node).condition) { + type = narrowType(type, (node).condition, /*assumeTrue*/ child === (node).whenTrue); + } + break; + case SyntaxKind.BinaryExpression: + // In the right operand of an && or ||, narrow based on left operand + if (child === (node).right) { + if ((node).operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) { + type = narrowType(type, (node).left, /*assumeTrue*/ true); + } + else if ((node).operatorToken.kind === SyntaxKind.BarBarToken) { + type = narrowType(type, (node).left, /*assumeTrue*/ false); + } + } + break; + default: + Debug.fail("Unreachable!"); + } + + // Use original type if construct contains assignments to variable + if (type !== originalType && isAnyPartOfReferenceAssignedWithin(reference, node)) { + type = originalType; + } + } + + // Preserve old top-level behavior - if the branch is really an empty set, revert to prior type + if (type === emptyUnionType) { + type = originalType; } return type; function narrowTypeByTruthiness(type: Type, expr: Identifier, assumeTrue: boolean): Type { - return strictNullChecks && assumeTrue && getResolvedSymbol(expr) === symbol ? getNonNullableType(type) : type; + return strictNullChecks && assumeTrue && isMatchingReference(expr, reference) ? getNonNullableType(type) : type; } function narrowTypeByBinaryExpression(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { @@ -7095,14 +7153,11 @@ namespace ts { } function narrowTypeByNullCheck(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { - // We have '==' or '!=' operator with 'null' on the right + // We have '==' or '!=' operator with 'null' or 'undefined' on the right if (expr.operatorToken.kind === SyntaxKind.ExclamationEqualsToken) { assumeTrue = !assumeTrue; } - if (!strictNullChecks || assumeTrue) { - return type; - } - if (expr.left.kind !== SyntaxKind.Identifier || getResolvedSymbol(expr.left) !== symbol) { + if (!strictNullChecks || assumeTrue || !isMatchingReference(expr.left, reference)) { return type; } return getNonNullableType(type); @@ -7113,7 +7168,7 @@ namespace ts { // and string literal on the right const left = expr.left; const right = expr.right; - if (left.expression.kind !== SyntaxKind.Identifier || getResolvedSymbol(left.expression) !== symbol) { + if (!isMatchingReference(left.expression, reference)) { return type; } if (expr.operatorToken.kind === SyntaxKind.ExclamationEqualsToken || @@ -7181,7 +7236,7 @@ namespace ts { function narrowTypeByInstanceof(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { // Check that type is not any, assumed result is true, and we have variable symbol on the left - if (isTypeAny(type) || expr.left.kind !== SyntaxKind.Identifier || getResolvedSymbol(expr.left) !== symbol) { + if (isTypeAny(type) || !isMatchingReference(expr.left, reference)) { return type; } @@ -7252,50 +7307,35 @@ namespace ts { return type; } const signature = getResolvedSignature(callExpression); - const predicate = signature.typePredicate; if (!predicate) { return type; } - if (isIdentifierTypePredicate(predicate)) { - if (callExpression.arguments[predicate.parameterIndex] && - getSymbolAtTypePredicatePosition(callExpression.arguments[predicate.parameterIndex]) === symbol) { + const predicateArgument = callExpression.arguments[predicate.parameterIndex]; + if (predicateArgument && isMatchingReference(predicateArgument, reference)) { return getNarrowedType(type, predicate.type, assumeTrue); } } else { const invokedExpression = skipParenthesizedNodes(callExpression.expression); - return narrowTypeByThisTypePredicate(type, predicate, invokedExpression, assumeTrue); - } - return type; - } - - function narrowTypeByThisTypePredicate(type: Type, predicate: ThisTypePredicate, invokedExpression: Expression, assumeTrue: boolean): Type { - if (invokedExpression.kind === SyntaxKind.ElementAccessExpression || invokedExpression.kind === SyntaxKind.PropertyAccessExpression) { - const accessExpression = invokedExpression as ElementAccessExpression | PropertyAccessExpression; - const possibleIdentifier = skipParenthesizedNodes(accessExpression.expression); - if (possibleIdentifier.kind === SyntaxKind.Identifier && getSymbolAtTypePredicatePosition(possibleIdentifier) === symbol) { - return getNarrowedType(type, predicate.type, assumeTrue); + if (invokedExpression.kind === SyntaxKind.ElementAccessExpression || invokedExpression.kind === SyntaxKind.PropertyAccessExpression) { + const accessExpression = invokedExpression as ElementAccessExpression | PropertyAccessExpression; + const possibleReference= skipParenthesizedNodes(accessExpression.expression); + if (isMatchingReference(possibleReference, reference)) { + return getNarrowedType(type, predicate.type, assumeTrue); + } } } return type; } - function getSymbolAtTypePredicatePosition(expr: Expression): Symbol { - expr = skipParenthesizedNodes(expr); - switch (expr.kind) { - case SyntaxKind.Identifier: - case SyntaxKind.PropertyAccessExpression: - return getSymbolOfEntityNameOrPropertyAccessExpression(expr as (Identifier | PropertyAccessExpression)); - } - } - // Narrow the given type based on the given expression having the assumed boolean value. The returned type // will be a subtype or the same type as the argument. function narrowType(type: Type, expr: Expression, assumeTrue: boolean): Type { switch (expr.kind) { case SyntaxKind.Identifier: + case SyntaxKind.PropertyAccessExpression: return narrowTypeByTruthiness(type, expr, assumeTrue); case SyntaxKind.CallExpression: return narrowTypeByTypePredicate(type, expr, assumeTrue); @@ -7313,6 +7353,16 @@ namespace ts { } } + function getTypeOfSymbolAtLocation(symbol: Symbol, location: Node) { + // The language service will always care about the narrowed type of a symbol, because that is + // the type the language says the symbol should have. + let type = getTypeOfSymbol(symbol); + if (location.kind === SyntaxKind.Identifier && isExpression(location) && getResolvedSymbol(location) === symbol) { + type = getNarrowedTypeOfReference(type, location); + } + return type; + } + function skipParenthesizedNodes(expression: Expression): Expression { while (expression.kind === SyntaxKind.ParenthesizedExpression) { expression = (expression as ParenthesizedExpression).expression; @@ -7371,7 +7421,7 @@ namespace ts { checkCollisionWithCapturedThisVariable(node, node); checkNestedBlockScopedBinding(node, symbol); - return getNarrowedTypeOfSymbol(localOrExportSymbol, node); + return getNarrowedTypeOfReference(getTypeOfSymbol(localOrExportSymbol), node); } function isInsideFunction(node: Node, threshold: Node): boolean { @@ -9122,7 +9172,10 @@ namespace ts { if (prop.parent && prop.parent.flags & SymbolFlags.Class) { checkClassPropertyAccess(node, left, apparentType, prop); } - return getTypeOfSymbol(prop); + + const propType = getTypeOfSymbol(prop); + return node.kind === SyntaxKind.PropertyAccessExpression && prop.flags & SymbolFlags.Property ? + getNarrowedTypeOfReference(propType, node) : propType; } function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 380bbdb3b90..b4b81c2732f 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -974,6 +974,8 @@ namespace ts { name: Identifier; } + export type IdentifierOrPropertyAccess = Identifier | PropertyAccessExpression; + // @kind(SyntaxKind.ElementAccessExpression) export interface ElementAccessExpression extends MemberExpression { expression: LeftHandSideExpression; @@ -2071,7 +2073,7 @@ namespace ts { isVisible?: boolean; // Is this node visible generatedName?: string; // Generated name for module, enum, or import declaration generatedNames?: Map; // Generated names table for source file - assignmentChecks?: Map; // Cache of assignment checks + assignmentMap?: Map; // Cached map of references assigned within this node hasReportedStatementInAmbientContext?: boolean; // Cache boolean if we report statements in ambient context importOnRightSide?: Symbol; // for import declarations - import that appear on the right side jsxFlags?: JsxFlags; // flags for knowing what kind of element/attributes we're dealing with From 82169ce7eb2e31c027fd2c9c37883faedb207c3c Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 27 Feb 2016 18:12:40 -0800 Subject: [PATCH 081/274] Fix getTypeOfSymbolAtLocation to handle hypothetical lookups --- src/compiler/checker.ts | 34 ++++++++++++++++++++++++++++++---- src/compiler/types.ts | 5 +++++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cd4a21204a2..b3be9545848 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6863,7 +6863,19 @@ namespace ts { // EXPRESSION TYPE CHECKING + function createTransientIdentifier(symbol: Symbol, location: Node): Identifier { + let result = createNode(SyntaxKind.Identifier); + result.text = symbol.name; + result.resolvedSymbol = symbol; + result.parent = location; + result.id = -1; + return result; + } + function getResolvedSymbol(node: Identifier): Symbol { + if (node.id === -1) { + return (node).resolvedSymbol; + } const links = getNodeLinks(node); if (!links.resolvedSymbol) { links.resolvedSymbol = !nodeIsMissing(node) && resolveName(node, node.text, SymbolFlags.Value | SymbolFlags.ExportValue, Diagnostics.Cannot_find_name_0, node) || unknownSymbol; @@ -7356,11 +7368,25 @@ namespace ts { function getTypeOfSymbolAtLocation(symbol: Symbol, location: Node) { // The language service will always care about the narrowed type of a symbol, because that is // the type the language says the symbol should have. - let type = getTypeOfSymbol(symbol); - if (location.kind === SyntaxKind.Identifier && isExpression(location) && getResolvedSymbol(location) === symbol) { - type = getNarrowedTypeOfReference(type, location); + const type = getTypeOfSymbol(symbol); + if (location.kind === SyntaxKind.Identifier) { + if (isRightSideOfQualifiedNameOrPropertyAccess(location)) { + location = location.parent; + } + // If location is an identifier or property access that references the given + // symbol, use the location as the reference with respect to which we narrow. + if (isExpression(location)) { + checkExpression(location); + if (getNodeLinks(location).resolvedSymbol === symbol) { + return getNarrowedTypeOfReference(type, location); + } + } } - return type; + // The location isn't a reference to the given symbol, meaning we're being asked + // a hypothetical question of what type the symbol would have if there was a reference + // to it at the given location. To answer that question we manufacture a transient + // identifier at the location and narrow with respect to that identifier. + return getNarrowedTypeOfReference(type, createTransientIdentifier(symbol, location)); } function skipParenthesizedNodes(expression: Expression): Expression { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index b4b81c2732f..840d7988405 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -476,6 +476,11 @@ namespace ts { originalKeywordKind?: SyntaxKind; // Original syntaxKind which get set so that we can report an error later } + // Transient identifier node (marked by id === -1) + export interface TransientIdentifier extends Identifier { + resolvedSymbol: Symbol; + } + // @kind(SyntaxKind.QualifiedName) export interface QualifiedName extends Node { // Must have same layout as PropertyAccess From 7dd59ceff6a20505b960ec319b4326689f816ff1 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 27 Feb 2016 18:13:26 -0800 Subject: [PATCH 082/274] Accepting new baselines --- .../reference/typeGuardFunctionOfFormThis.types | 4 ++-- .../reference/typeGuardsInProperties.types | 16 ++++++++-------- .../typeGuardsOnClassProperty.errors.txt | 5 +---- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/tests/baselines/reference/typeGuardFunctionOfFormThis.types b/tests/baselines/reference/typeGuardFunctionOfFormThis.types index 6b21fea3457..cd0381a94e9 100644 --- a/tests/baselines/reference/typeGuardFunctionOfFormThis.types +++ b/tests/baselines/reference/typeGuardFunctionOfFormThis.types @@ -174,9 +174,9 @@ if (holder2.a.isLeader()) { >isLeader : () => this is LeadGuard holder2.a; ->holder2.a : RoyalGuard +>holder2.a : LeadGuard >holder2 : { a: RoyalGuard; } ->a : RoyalGuard +>a : LeadGuard } else { holder2.a; diff --git a/tests/baselines/reference/typeGuardsInProperties.types b/tests/baselines/reference/typeGuardsInProperties.types index ca4d8b94527..d6c9602a450 100644 --- a/tests/baselines/reference/typeGuardsInProperties.types +++ b/tests/baselines/reference/typeGuardsInProperties.types @@ -76,18 +76,18 @@ var c1: C1; >C1 : C1 strOrNum = typeof c1.pp2 === "string" && c1.pp2; // string | number ->strOrNum = typeof c1.pp2 === "string" && c1.pp2 : string | number +>strOrNum = typeof c1.pp2 === "string" && c1.pp2 : string >strOrNum : string | number ->typeof c1.pp2 === "string" && c1.pp2 : string | number +>typeof c1.pp2 === "string" && c1.pp2 : string >typeof c1.pp2 === "string" : boolean >typeof c1.pp2 : string >c1.pp2 : string | number >c1 : C1 >pp2 : string | number >"string" : string ->c1.pp2 : string | number +>c1.pp2 : string >c1 : C1 ->pp2 : string | number +>pp2 : string strOrNum = typeof c1.pp3 === "string" && c1.pp3; // string | number >strOrNum = typeof c1.pp3 === "string" && c1.pp3 : string | number @@ -111,16 +111,16 @@ var obj1: { }; strOrNum = typeof obj1.x === "string" && obj1.x; // string | number ->strOrNum = typeof obj1.x === "string" && obj1.x : string | number +>strOrNum = typeof obj1.x === "string" && obj1.x : string >strOrNum : string | number ->typeof obj1.x === "string" && obj1.x : string | number +>typeof obj1.x === "string" && obj1.x : string >typeof obj1.x === "string" : boolean >typeof obj1.x : string >obj1.x : string | number >obj1 : { x: string | number; } >x : string | number >"string" : string ->obj1.x : string | number +>obj1.x : string >obj1 : { x: string | number; } ->x : string | number +>x : string diff --git a/tests/baselines/reference/typeGuardsOnClassProperty.errors.txt b/tests/baselines/reference/typeGuardsOnClassProperty.errors.txt index 91d6d6998bc..660962ec1a7 100644 --- a/tests/baselines/reference/typeGuardsOnClassProperty.errors.txt +++ b/tests/baselines/reference/typeGuardsOnClassProperty.errors.txt @@ -1,8 +1,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsOnClassProperty.ts(14,70): error TS2339: Property 'join' does not exist on type 'string | string[]'. -tests/cases/conformance/expressions/typeGuards/typeGuardsOnClassProperty.ts(26,44): error TS2339: Property 'toLowerCase' does not exist on type 'number | string'. -==== tests/cases/conformance/expressions/typeGuards/typeGuardsOnClassProperty.ts (2 errors) ==== +==== tests/cases/conformance/expressions/typeGuards/typeGuardsOnClassProperty.ts (1 errors) ==== // Note that type guards affect types of variables and parameters only and // have no effect on members of objects such as properties. @@ -31,7 +30,5 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsOnClassProperty.ts(26,4 } if (typeof o.prop1 === "string" && o.prop1.toLowerCase()) {} - ~~~~~~~~~~~ -!!! error TS2339: Property 'toLowerCase' does not exist on type 'number | string'. var prop1 = o.prop1; if (typeof prop1 === "string" && prop1.toLocaleLowerCase()) { } \ No newline at end of file From ea3593239cde31d2cd35788d97bce5204b985b19 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 28 Feb 2016 10:30:19 -0800 Subject: [PATCH 083/274] Fix linting error --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b3be9545848..80aadc977a9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6864,7 +6864,7 @@ namespace ts { // EXPRESSION TYPE CHECKING function createTransientIdentifier(symbol: Symbol, location: Node): Identifier { - let result = createNode(SyntaxKind.Identifier); + const result = createNode(SyntaxKind.Identifier); result.text = symbol.name; result.resolvedSymbol = symbol; result.parent = location; From 33e3825beb4aa7b8114923a7126eb3f27779d410 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 2 Mar 2016 16:40:16 -0800 Subject: [PATCH 084/274] Assigned-before-use checking for non-nullable variables --- src/compiler/checker.ts | 143 ++++++++++++++++++++++++--- src/compiler/diagnosticMessages.json | 4 + src/compiler/types.ts | 4 +- 3 files changed, 135 insertions(+), 16 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 80aadc977a9..89517b7539e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6929,9 +6929,9 @@ namespace ts { visit(node); return assignmentMap; - function visitBinaryExpression(node: BinaryExpression) { - if (node.operatorToken.kind >= SyntaxKind.FirstAssignment && node.operatorToken.kind <= SyntaxKind.LastAssignment) { - const key = getAssignmentKey(skipParenthesizedNodes(node.left)); + function visitReference(node: Identifier | PropertyAccessExpression) { + if (isAssignmentTarget(node) || isCompoundAssignmentTarget(node)) { + const key = getAssignmentKey(node); if (key) { assignmentMap[key] = true; } @@ -6948,18 +6948,19 @@ namespace ts { function visit(node: Node) { switch (node.kind) { - case SyntaxKind.BinaryExpression: - visitBinaryExpression(node); + case SyntaxKind.Identifier: + case SyntaxKind.PropertyAccessExpression: + visitReference(node); break; case SyntaxKind.VariableDeclaration: case SyntaxKind.BindingElement: visitVariableDeclaration(node); break; + case SyntaxKind.BinaryExpression: case SyntaxKind.ObjectBindingPattern: case SyntaxKind.ArrayBindingPattern: case SyntaxKind.ArrayLiteralExpression: case SyntaxKind.ObjectLiteralExpression: - case SyntaxKind.PropertyAccessExpression: case SyntaxKind.ElementAccessExpression: case SyntaxKind.CallExpression: case SyntaxKind.NewExpression: @@ -7396,6 +7397,93 @@ namespace ts { return expression; } + function findFirstAssignment(symbol: Symbol, container: Node): Node { + return visit(isFunctionLike(container) ? (container).body : container); + + function visit(node: Node): Node { + switch (node.kind) { + case SyntaxKind.Identifier: + const assignment = getAssignmentRoot(node); + return assignment && getResolvedSymbol(node) === symbol ? assignment : undefined; + case SyntaxKind.BinaryExpression: + case SyntaxKind.VariableDeclaration: + case SyntaxKind.BindingElement: + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.ArrayBindingPattern: + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: + case SyntaxKind.CallExpression: + case SyntaxKind.NewExpression: + case SyntaxKind.TypeAssertionExpression: + case SyntaxKind.AsExpression: + case SyntaxKind.NonNullExpression: + case SyntaxKind.ParenthesizedExpression: + case SyntaxKind.PrefixUnaryExpression: + case SyntaxKind.DeleteExpression: + case SyntaxKind.AwaitExpression: + case SyntaxKind.TypeOfExpression: + case SyntaxKind.VoidExpression: + case SyntaxKind.PostfixUnaryExpression: + case SyntaxKind.YieldExpression: + case SyntaxKind.ConditionalExpression: + case SyntaxKind.SpreadElementExpression: + case SyntaxKind.VariableStatement: + case SyntaxKind.ExpressionStatement: + case SyntaxKind.IfStatement: + case SyntaxKind.DoStatement: + case SyntaxKind.WhileStatement: + case SyntaxKind.ForStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + case SyntaxKind.ReturnStatement: + case SyntaxKind.WithStatement: + case SyntaxKind.SwitchStatement: + case SyntaxKind.CaseClause: + case SyntaxKind.DefaultClause: + case SyntaxKind.LabeledStatement: + case SyntaxKind.ThrowStatement: + case SyntaxKind.TryStatement: + case SyntaxKind.CatchClause: + case SyntaxKind.JsxElement: + case SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.JsxAttribute: + case SyntaxKind.JsxSpreadAttribute: + case SyntaxKind.JsxOpeningElement: + case SyntaxKind.JsxExpression: + case SyntaxKind.Block: + case SyntaxKind.SourceFile: + return forEachChild(node, visit); + } + return undefined; + } + } + + function checkVariableAssignedBefore(symbol: Symbol, reference: Node) { + if (!(symbol.flags & SymbolFlags.Variable)) { + return; + } + const declaration = symbol.valueDeclaration; + if (!declaration || declaration.kind !== SyntaxKind.VariableDeclaration || (declaration).initializer) { + return; + } + const declarationContainer = getContainingFunction(declaration) || getSourceFileOfNode(declaration); + const referenceContainer = getContainingFunction(reference) || getSourceFileOfNode(reference); + if (declarationContainer !== referenceContainer) { + return; + } + const links = getSymbolLinks(symbol); + if (!links.firstAssignmentChecked) { + links.firstAssignmentChecked = true; + links.firstAssignment = findFirstAssignment(symbol, declarationContainer); + } + if (links.firstAssignment && links.firstAssignment.end <= reference.pos) { + return; + } + error(reference, Diagnostics.Variable_0_is_used_before_being_assigned, symbolToString(symbol)); + } + function checkIdentifier(node: Identifier): Type { const symbol = getResolvedSymbol(node); @@ -7447,7 +7535,11 @@ namespace ts { checkCollisionWithCapturedThisVariable(node, node); checkNestedBlockScopedBinding(node, symbol); - return getNarrowedTypeOfReference(getTypeOfSymbol(localOrExportSymbol), node); + const type = getTypeOfSymbol(localOrExportSymbol); + if (strictNullChecks && !isAssignmentTarget(node) && !(type.flags & TypeFlags.Any) && !isNullableType(type)) { + checkVariableAssignedBefore(symbol, node); + } + return getNarrowedTypeOfReference(type, node); } function isInsideFunction(node: Node, threshold: Node): boolean { @@ -8344,19 +8436,40 @@ namespace ts { return mapper && mapper.context; } + // Return the root assignment node of an assignment target + function getAssignmentRoot(node: Node): Node { + while (node.parent.kind === SyntaxKind.ParenthesizedExpression) { + node = node.parent; + } + while (true) { + if (node.parent.kind === SyntaxKind.PropertyAssignment) { + node = node.parent.parent; + } + else if (node.parent.kind === SyntaxKind.ArrayLiteralExpression) { + node = node.parent; + } + else { + break; + } + } + const parent = node.parent; + return parent.kind === SyntaxKind.BinaryExpression && + (parent).operatorToken.kind === SyntaxKind.EqualsToken && + (parent).left === node ? parent : undefined; + } + // A node is an assignment target if it is on the left hand side of an '=' token, if it is parented by a property // assignment in an object literal that is an assignment target, or if it is parented by an array literal that is // an assignment target. Examples include 'a = xxx', '{ p: a } = xxx', '[{ p: a}] = xxx'. function isAssignmentTarget(node: Node): boolean { + return !!getAssignmentRoot(node); + } + + function isCompoundAssignmentTarget(node: Node) { const parent = node.parent; - if (parent.kind === SyntaxKind.BinaryExpression && (parent).operatorToken.kind === SyntaxKind.EqualsToken && (parent).left === node) { - return true; - } - if (parent.kind === SyntaxKind.PropertyAssignment) { - return isAssignmentTarget(parent.parent); - } - if (parent.kind === SyntaxKind.ArrayLiteralExpression) { - return isAssignmentTarget(parent); + if (parent.kind === SyntaxKind.BinaryExpression && (parent).left === node) { + const operator = (parent).operatorToken.kind; + return operator >= SyntaxKind.FirstAssignment && operator <= SyntaxKind.LastAssignment; } return false; } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 09a9795eccd..0b70ab98ce7 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1411,6 +1411,10 @@ "category": "Error", "code": 2453 }, + "Variable '{0}' is used before being assigned.": { + "category": "Error", + "code": 2454 + }, "Type argument candidate '{1}' is not a valid type argument because it is not a supertype of candidate '{0}'.": { "category": "Error", "code": 2455 diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 840d7988405..ea3d95c49eb 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2035,7 +2035,9 @@ namespace ts { exportsChecked?: boolean; // True if exports of external module have been checked isDeclarationWithCollidingName?: boolean; // True if symbol is block scoped redeclaration bindingElement?: BindingElement; // Binding element associated with property symbol - exportsSomeValue?: boolean; // true if module exports some value (not just types) + exportsSomeValue?: boolean; // True if module exports some value (not just types) + firstAssignmentChecked?: boolean; // True if first assignment node has been computed + firstAssignment?: Node; // First assignment node (undefined if no assignments) } /* @internal */ From 99edce09bc1707ff6d41310a1174e85161355eac Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Thu, 3 Mar 2016 13:29:00 +0800 Subject: [PATCH 085/274] Fixes CR feedback --- src/services/navigationBar.ts | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index b537a56e856..2d06177e128 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -155,18 +155,18 @@ namespace ts.NavigationBar { switch (node.kind) { case SyntaxKind.ClassDeclaration: topLevelNodes.push(node); - forEach((node).members, (node) => { - if (node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.Constructor) { + for (const member of (node).members) { + if (member.kind === SyntaxKind.MethodDeclaration || member.kind === SyntaxKind.Constructor) { type FunctionLikeMember = MethodDeclaration | ConstructorDeclaration; - if ((node).body) { + if ((member).body) { // We do not include methods that does not have child functions in it, because of duplications. - if (hasNonAnonymousFunctionDeclarations(((node).body).statements)) { - topLevelNodes.push(node); + if (hasNamedFunctionDeclarations(((member).body).statements)) { + topLevelNodes.push(member); } - addTopLevelNodes(((node).body).statements, topLevelNodes); + addTopLevelNodes(((member).body).statements, topLevelNodes); } } - }); + } break; case SyntaxKind.EnumDeclaration: case SyntaxKind.InterfaceDeclaration: @@ -190,7 +190,7 @@ namespace ts.NavigationBar { } } - function hasNonAnonymousFunctionDeclarations(nodes: NodeArray) { + function hasNamedFunctionDeclarations(nodes: NodeArray) { if (forEach(nodes, s => s.kind === SyntaxKind.FunctionDeclaration && !isEmpty((s).name.text))) { return true; } @@ -202,12 +202,11 @@ namespace ts.NavigationBar { // within it. if (functionDeclaration.body && functionDeclaration.body.kind === SyntaxKind.Block) { // Proper function declarations can only have identifier names - if (hasNonAnonymousFunctionDeclarations((functionDeclaration.body).statements)) { - + if (hasNamedFunctionDeclarations((functionDeclaration.body).statements)) { return true; } - // Or if it is not parented by another function(except for parent functions that + // Or if it is not parented by another function (except for parent functions that // are methods and constructors). I.e all functions at module scope are 'top level'. if (!isFunctionBlock(functionDeclaration.parent)) { return true; From ea4b13bdf94fb2241f15874d9d0b0cead15d6784 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 3 Mar 2016 11:18:12 -0800 Subject: [PATCH 086/274] Allow 'null' and 'undefined' as type names --- src/compiler/checker.ts | 6 ++++++ src/compiler/declarationEmitter.ts | 2 ++ src/compiler/parser.ts | 4 ++++ src/compiler/scanner.ts | 1 + src/compiler/types.ts | 1 + src/compiler/utilities.ts | 1 + 6 files changed, 15 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 89517b7539e..71ef823d137 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3411,6 +3411,8 @@ namespace ts { case SyntaxKind.BooleanKeyword: case SyntaxKind.SymbolKeyword: case SyntaxKind.VoidKeyword: + case SyntaxKind.UndefinedKeyword: + case SyntaxKind.NullKeyword: case SyntaxKind.StringLiteralType: return true; case SyntaxKind.ArrayType: @@ -4935,6 +4937,10 @@ namespace ts { return esSymbolType; case SyntaxKind.VoidKeyword: return voidType; + case SyntaxKind.UndefinedKeyword: + return undefinedType; + case SyntaxKind.NullKeyword: + return nullType; case SyntaxKind.ThisType: return getTypeFromThisTypeNode(node); case SyntaxKind.StringLiteralType: diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index 1328a2e8484..d2031a7bad6 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -367,6 +367,8 @@ namespace ts { case SyntaxKind.BooleanKeyword: case SyntaxKind.SymbolKeyword: case SyntaxKind.VoidKeyword: + case SyntaxKind.UndefinedKeyword: + case SyntaxKind.NullKeyword: case SyntaxKind.ThisType: case SyntaxKind.StringLiteralType: return writeTextOfNode(currentText, type); diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index a7e76ac3ae4..c2d3173a860 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -2379,12 +2379,14 @@ namespace ts { case SyntaxKind.NumberKeyword: case SyntaxKind.BooleanKeyword: case SyntaxKind.SymbolKeyword: + case SyntaxKind.UndefinedKeyword: // If these are followed by a dot, then parse these out as a dotted type reference instead. const node = tryParse(parseKeywordAndNoDot); return node || parseTypeReference(); case SyntaxKind.StringLiteral: return parseStringLiteralTypeNode(); case SyntaxKind.VoidKeyword: + case SyntaxKind.NullKeyword: return parseTokenNode(); case SyntaxKind.ThisKeyword: { const thisKeyword = parseThisTypeNode(); @@ -2416,6 +2418,8 @@ namespace ts { case SyntaxKind.BooleanKeyword: case SyntaxKind.SymbolKeyword: case SyntaxKind.VoidKeyword: + case SyntaxKind.UndefinedKeyword: + case SyntaxKind.NullKeyword: case SyntaxKind.ThisKeyword: case SyntaxKind.TypeOfKeyword: case SyntaxKind.OpenBraceToken: diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 64747fc638c..8979814a7a2 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -114,6 +114,7 @@ namespace ts { "try": SyntaxKind.TryKeyword, "type": SyntaxKind.TypeKeyword, "typeof": SyntaxKind.TypeOfKeyword, + "undefined": SyntaxKind.UndefinedKeyword, "var": SyntaxKind.VarKeyword, "void": SyntaxKind.VoidKeyword, "while": SyntaxKind.WhileKeyword, diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ea3d95c49eb..9f709c8fa68 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -171,6 +171,7 @@ namespace ts { StringKeyword, SymbolKeyword, TypeKeyword, + UndefinedKeyword, FromKeyword, GlobalKeyword, OfKeyword, // LastKeyword and LastToken diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 7012326fa98..953e2a7c194 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -515,6 +515,7 @@ namespace ts { case SyntaxKind.StringKeyword: case SyntaxKind.BooleanKeyword: case SyntaxKind.SymbolKeyword: + case SyntaxKind.UndefinedKeyword: return true; case SyntaxKind.VoidKeyword: return node.parent.kind !== SyntaxKind.VoidExpression; From ed958119a179ffa4ca1280abfefda0a5dc7e9e9d Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 3 Mar 2016 11:18:33 -0800 Subject: [PATCH 087/274] Fix unit test --- tests/cases/unittests/jsDocParsing.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index 9988383b467..5553ea77b8f 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -792,6 +792,7 @@ module ts { "kind": "Identifier", "pos": 1, "end": 10, + "originalKeywordKind": "UndefinedKeyword", "text": "undefined" } }`); From 04c28b09a9c20fe71fb1555cdce0f25647eca8e9 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 3 Mar 2016 11:18:47 -0800 Subject: [PATCH 088/274] Accepting new baselines --- .../reference/typeParameterConstraints1.errors.txt | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/tests/baselines/reference/typeParameterConstraints1.errors.txt b/tests/baselines/reference/typeParameterConstraints1.errors.txt index e837e19317d..97bc8165751 100644 --- a/tests/baselines/reference/typeParameterConstraints1.errors.txt +++ b/tests/baselines/reference/typeParameterConstraints1.errors.txt @@ -1,11 +1,9 @@ tests/cases/compiler/typeParameterConstraints1.ts(6,25): error TS2304: Cannot find name 'hm'. tests/cases/compiler/typeParameterConstraints1.ts(9,25): error TS1110: Type expected. tests/cases/compiler/typeParameterConstraints1.ts(10,26): error TS1110: Type expected. -tests/cases/compiler/typeParameterConstraints1.ts(11,26): error TS1110: Type expected. -tests/cases/compiler/typeParameterConstraints1.ts(12,26): error TS2304: Cannot find name 'undefined'. -==== tests/cases/compiler/typeParameterConstraints1.ts (5 errors) ==== +==== tests/cases/compiler/typeParameterConstraints1.ts (3 errors) ==== function foo1(test: T) { } function foo2(test: T) { } function foo3(test: T) { } @@ -23,9 +21,5 @@ tests/cases/compiler/typeParameterConstraints1.ts(12,26): error TS2304: Cannot f ~ !!! error TS1110: Type expected. function foo11 (test: T) { } - ~~~~ -!!! error TS1110: Type expected. function foo12(test: T) { } - ~~~~~~~~~ -!!! error TS2304: Cannot find name 'undefined'. function foo13(test: T) { } \ No newline at end of file From 87ae0489eb8b0b9f4fac16f8dd503a56978bb58b Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 3 Mar 2016 17:44:46 -0800 Subject: [PATCH 089/274] Reinstate separate type kinds for 'null' and 'undefined' --- src/compiler/checker.ts | 100 +++++++++++++++++++++++++++------------- src/compiler/types.ts | 19 ++++---- 2 files changed, 77 insertions(+), 42 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 71ef823d137..70f1a31e186 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -113,9 +113,9 @@ namespace ts { const booleanType = createIntrinsicType(TypeFlags.Boolean, "boolean"); const esSymbolType = createIntrinsicType(TypeFlags.ESSymbol, "symbol"); const voidType = createIntrinsicType(TypeFlags.Void, "void"); - const undefinedType = createIntrinsicType(TypeFlags.Undefined | TypeFlags.ContainsUndefined, "undefined"); - const nullType = createIntrinsicType(TypeFlags.Undefined | TypeFlags.ContainsUndefined, "null"); - const emptyArrayElementType = createIntrinsicType(TypeFlags.Undefined | TypeFlags.ContainsUndefined, "undefined"); + const undefinedType = createIntrinsicType(TypeFlags.Undefined | TypeFlags.ContainsUndefinedOrNull, "undefined"); + const nullType = createIntrinsicType(TypeFlags.Null | TypeFlags.ContainsUndefinedOrNull, "null"); + const emptyArrayElementType = createIntrinsicType(TypeFlags.Undefined | TypeFlags.ContainsUndefinedOrNull, "undefined"); const unknownType = createIntrinsicType(TypeFlags.Any, "unknown"); const emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); @@ -209,7 +209,7 @@ namespace ts { }, "undefined": { type: undefinedType, - flags: TypeFlags.ContainsUndefined + flags: TypeFlags.ContainsUndefinedOrNull } }; @@ -1883,7 +1883,7 @@ namespace ts { else if (type.flags & TypeFlags.Tuple) { writeTupleType(type); } - else if (isNullableType(type)) { + else if (isNullableType(type) && (type).types.length > 2) { writeType(getNonNullableType(type), TypeFormatFlags.InElementType); writePunctuation(writer, SyntaxKind.QuestionToken); } @@ -4805,7 +4805,7 @@ namespace ts { const id = getTypeListId(typeSet); let type = unionTypes[id]; if (!type) { - const propagatedFlags = getPropagatingFlagsOfTypes(typeSet, /*excludeKinds*/ TypeFlags.Undefined); + const propagatedFlags = getPropagatingFlagsOfTypes(typeSet, /*excludeKinds*/ TypeFlags.Nullable); type = unionTypes[id] = createObjectType(TypeFlags.Union | propagatedFlags); type.types = typeSet; } @@ -4840,7 +4840,7 @@ namespace ts { const id = getTypeListId(typeSet); let type = intersectionTypes[id]; if (!type) { - const propagatedFlags = getPropagatingFlagsOfTypes(typeSet, /*excludeKinds*/ TypeFlags.Undefined); + const propagatedFlags = getPropagatingFlagsOfTypes(typeSet, /*excludeKinds*/ TypeFlags.Nullable); type = intersectionTypes[id] = createObjectType(TypeFlags.Intersection | propagatedFlags); type.types = typeSet; } @@ -5502,6 +5502,9 @@ namespace ts { if (source.flags & TypeFlags.Undefined) { if (!strictNullChecks || target.flags & TypeFlags.Undefined || source === emptyArrayElementType) return Ternary.True; } + if (source.flags & TypeFlags.Null) { + if (!strictNullChecks || target.flags & TypeFlags.Null) return Ternary.True; + } if (source.flags & TypeFlags.Enum && target === numberType) return Ternary.True; if (source.flags & TypeFlags.Enum && target.flags & TypeFlags.Enum) { if (result = enumRelatedTo(source, target)) { @@ -6325,7 +6328,7 @@ namespace ts { // A type is array-like if it is a reference to the global Array or global ReadonlyArray type, // or if it is not the undefined or null type and if it is assignable to ReadonlyArray return type.flags & TypeFlags.Reference && ((type).target === globalArrayType || (type).target === globalReadonlyArrayType) || - !(type.flags & TypeFlags.Undefined) && isTypeAssignableTo(type, anyReadonlyArrayType); + !(type.flags & TypeFlags.Nullable) && isTypeAssignableTo(type, anyReadonlyArrayType); } function isTupleLikeType(type: Type): boolean { @@ -6344,18 +6347,18 @@ namespace ts { return !!(type.flags & TypeFlags.Tuple); } - function isNullableType(type: Type): boolean { - if (type.flags & TypeFlags.Undefined) { - return true; - } - if (type.flags & TypeFlags.Union) { + function getNullableKind(type: Type): TypeFlags { + let flags = type.flags; + if (flags & TypeFlags.Union) { for (const t of (type as UnionType).types) { - if (t.flags & TypeFlags.Undefined) { - return true; - } + flags |= t.flags; } } - return false; + return flags & TypeFlags.Nullable; + } + + function isNullableType(type: Type) { + return getNullableKind(type) === TypeFlags.Nullable; } function getNullableType(type: Type): Type { @@ -6363,20 +6366,51 @@ namespace ts { return type; } if (!type.nullableType) { - type.nullableType = isNullableType(type) ? type : getUnionType([type, undefinedType]); + type.nullableType = isNullableType(type) ? type : getUnionType([type, undefinedType, nullType]); } return type.nullableType; } - function getNonNullableTypeFromUnionType(type: UnionType): Type { - if (!type.nonNullableType) { - type.nonNullableType = removeTypesFromUnionOrIntersection(type, [undefinedType, nullType]); + function addNullableKind(type: Type, kind: TypeFlags): Type { + if ((getNullableKind(type) & kind) !== kind) { + const types = [type]; + if (kind & TypeFlags.Undefined) { + types.push(undefinedType); + } + if (kind & TypeFlags.Null) { + types.push(nullType); + } + type = getUnionType(types); } - return type.nonNullableType; + return type; + } + + function removeNullableKind(type: Type, kind: TypeFlags) { + if (type.flags & TypeFlags.Union && getNullableKind(type) & kind) { + let firstType: Type; + let types: Type[]; + for (const t of (type as UnionType).types) { + if (!(t.flags & kind)) { + if (!firstType) { + firstType = t; + } + else { + if (!types) { + types = [firstType]; + } + types.push(t); + } + } + } + if (firstType) { + type = types ? getUnionType(types) : firstType; + } + } + return type; } function getNonNullableType(type: Type): Type { - return strictNullChecks && type.flags & TypeFlags.Union ? getNonNullableTypeFromUnionType(type as UnionType) : type; + return strictNullChecks ? removeNullableKind(type, TypeFlags.Nullable) : type; } /** @@ -6433,12 +6467,12 @@ namespace ts { } function getWidenedConstituentType(type: Type): Type { - return type.flags & TypeFlags.Undefined ? type : getWidenedType(type); + return type.flags & TypeFlags.Nullable ? type : getWidenedType(type); } function getWidenedType(type: Type): Type { if (type.flags & TypeFlags.RequiresWidening) { - if (type.flags & TypeFlags.Undefined) { + if (type.flags & TypeFlags.Nullable) { return anyType; } if (type.flags & TypeFlags.ObjectLiteral) { @@ -6490,7 +6524,7 @@ namespace ts { if (type.flags & TypeFlags.ObjectLiteral) { for (const p of getPropertiesOfObjectType(type)) { const t = getTypeOfSymbol(p); - if (t.flags & TypeFlags.ContainsUndefined) { + if (t.flags & TypeFlags.ContainsUndefinedOrNull) { if (!reportWideningErrorsInType(t)) { error(p.valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, p.name, typeToString(getWidenedType(t))); } @@ -6534,7 +6568,7 @@ namespace ts { } function reportErrorsFromWidening(declaration: Declaration, type: Type) { - if (produceDiagnostics && compilerOptions.noImplicitAny && type.flags & TypeFlags.ContainsUndefined) { + if (produceDiagnostics && compilerOptions.noImplicitAny && type.flags & TypeFlags.ContainsUndefinedOrNull) { // Report implicit any error within type if possible, otherwise report error on declaration if (!reportWideningErrorsInType(type)) { reportImplicitAnyError(declaration, type); @@ -7542,7 +7576,7 @@ namespace ts { checkNestedBlockScopedBinding(node, symbol); const type = getTypeOfSymbol(localOrExportSymbol); - if (strictNullChecks && !isAssignmentTarget(node) && !(type.flags & TypeFlags.Any) && !isNullableType(type)) { + if (strictNullChecks && !isAssignmentTarget(node) && !(type.flags & TypeFlags.Any) && !(getNullableKind(type) & TypeFlags.Undefined)) { checkVariableAssignedBefore(symbol, node); } return getNarrowedTypeOfReference(type, node); @@ -11524,8 +11558,8 @@ namespace ts { // as having the primitive type Number. If one operand is the null or undefined value, // it is treated as having the type of the other operand. // The result is always of the Number primitive type. - if (leftType.flags & TypeFlags.Undefined) leftType = rightType; - if (rightType.flags & TypeFlags.Undefined) rightType = leftType; + if (leftType.flags & TypeFlags.Nullable) leftType = rightType; + if (rightType.flags & TypeFlags.Nullable) rightType = leftType; leftType = getNonNullableType(leftType); rightType = getNonNullableType(rightType); @@ -11555,8 +11589,8 @@ namespace ts { // or at least one of the operands to be of type Any or the String primitive type. // If one operand is the null or undefined value, it is treated as having the type of the other operand. - if (leftType.flags & TypeFlags.Undefined) leftType = rightType; - if (rightType.flags & TypeFlags.Undefined) rightType = leftType; + if (leftType.flags & TypeFlags.Nullable) leftType = rightType; + if (rightType.flags & TypeFlags.Nullable) rightType = leftType; leftType = getNonNullableType(leftType); rightType = getNonNullableType(rightType); @@ -11618,7 +11652,7 @@ namespace ts { case SyntaxKind.InKeyword: return checkInExpression(left, right, leftType, rightType); case SyntaxKind.AmpersandAmpersandToken: - return isNullableType(leftType) ? getNullableType(rightType) : rightType; + return addNullableKind(rightType, getNullableKind(leftType)); case SyntaxKind.BarBarToken: return getUnionType([getNonNullableType(leftType), rightType]); case SyntaxKind.EqualsToken: diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 9f709c8fa68..56611961998 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2096,7 +2096,8 @@ namespace ts { Number = 0x00000004, Boolean = 0x00000008, Void = 0x00000010, - Undefined = 0x00000020, // Undefined or null + Undefined = 0x00000020, + Null = 0x00000040, Enum = 0x00000080, // Enum type StringLiteral = 0x00000100, // String literal type TypeParameter = 0x00000200, // Type parameter @@ -2114,7 +2115,7 @@ namespace ts { /* @internal */ FreshObjectLiteral = 0x00100000, // Fresh object literal type /* @internal */ - ContainsUndefined = 0x00200000, // Type is or contains undefined type + ContainsUndefinedOrNull = 0x00200000, // Type is or contains undefined or null type /* @internal */ ContainsObjectLiteral = 0x00400000, // Type is or contains object literal type /* @internal */ @@ -2124,18 +2125,20 @@ namespace ts { ObjectLiteralPatternWithComputedProperties = 0x04000000, // Object literal type implied by binding pattern has computed properties /* @internal */ - Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined, + Nullable = Undefined | Null, /* @internal */ - Primitive = String | Number | Boolean | ESSymbol | Void | Undefined | StringLiteral | Enum, + Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null, + /* @internal */ + Primitive = String | Number | Boolean | ESSymbol | Void | Undefined | Null | StringLiteral | Enum, StringLike = String | StringLiteral, NumberLike = Number | Enum, ObjectType = Class | Interface | Reference | Tuple | Anonymous, UnionOrIntersection = Union | Intersection, StructuredType = ObjectType | Union | Intersection, /* @internal */ - RequiresWidening = ContainsUndefined | ContainsObjectLiteral, + RequiresWidening = ContainsUndefinedOrNull | ContainsObjectLiteral, /* @internal */ - PropagatingFlags = ContainsUndefined | ContainsObjectLiteral | ContainsAnyFunctionType + PropagatingFlags = ContainsUndefinedOrNull | ContainsObjectLiteral | ContainsAnyFunctionType } export type DestructuringPattern = BindingPattern | ObjectLiteralExpression | ArrayLiteralExpression; @@ -2214,9 +2217,7 @@ namespace ts { resolvedProperties: SymbolTable; // Cache of resolved properties } - export interface UnionType extends UnionOrIntersectionType { - nonNullableType?: Type; // Cached non-nullable form of type - } + export interface UnionType extends UnionOrIntersectionType { } export interface IntersectionType extends UnionOrIntersectionType { } From c623e1f8c91950a0996273cec8d59781279023b2 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 4 Mar 2016 10:42:23 -0800 Subject: [PATCH 090/274] No widening of 'null' and 'undefined' types in --strictNullChecks mode --- src/compiler/checker.ts | 47 ++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 70f1a31e186..1e693867baf 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -107,14 +107,15 @@ namespace ts { const unknownSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "unknown"); const resolvingSymbol = createSymbol(SymbolFlags.Transient, "__resolving__"); + const nullableWideningFlags = strictNullChecks ? 0 : TypeFlags.ContainsUndefinedOrNull; const anyType = createIntrinsicType(TypeFlags.Any, "any"); const stringType = createIntrinsicType(TypeFlags.String, "string"); const numberType = createIntrinsicType(TypeFlags.Number, "number"); const booleanType = createIntrinsicType(TypeFlags.Boolean, "boolean"); const esSymbolType = createIntrinsicType(TypeFlags.ESSymbol, "symbol"); const voidType = createIntrinsicType(TypeFlags.Void, "void"); - const undefinedType = createIntrinsicType(TypeFlags.Undefined | TypeFlags.ContainsUndefinedOrNull, "undefined"); - const nullType = createIntrinsicType(TypeFlags.Null | TypeFlags.ContainsUndefinedOrNull, "null"); + const undefinedType = createIntrinsicType(TypeFlags.Undefined | nullableWideningFlags, "undefined"); + const nullType = createIntrinsicType(TypeFlags.Null | nullableWideningFlags, "null"); const emptyArrayElementType = createIntrinsicType(TypeFlags.Undefined | TypeFlags.ContainsUndefinedOrNull, "undefined"); const unknownType = createIntrinsicType(TypeFlags.Any, "unknown"); @@ -4719,10 +4720,21 @@ namespace ts { return links.resolvedType; } - function addTypeToSet(typeSet: Type[], type: Type, typeSetKind: TypeFlags) { + interface TypeSet extends Array { + containsAny?: boolean; + containsUndefined?: boolean; + containsNull?: boolean; + } + + function addTypeToSet(typeSet: TypeSet, type: Type, typeSetKind: TypeFlags) { if (type.flags & typeSetKind) { addTypesToSet(typeSet, (type).types, typeSetKind); } + else if (type.flags & (TypeFlags.Any | TypeFlags.Undefined | TypeFlags.Null)) { + if (type.flags & TypeFlags.Any) typeSet.containsAny = true; + if (type.flags & TypeFlags.Undefined) typeSet.containsUndefined = true; + if (type.flags & TypeFlags.Null) typeSet.containsNull = true; + } else if (!contains(typeSet, type)) { typeSet.push(type); } @@ -4730,7 +4742,7 @@ namespace ts { // Add the given types to the given type set. Order is preserved, duplicates are removed, // and nested types of the given kind are flattened into the set. - function addTypesToSet(typeSet: Type[], types: Type[], typeSetKind: TypeFlags) { + function addTypesToSet(typeSet: TypeSet, types: Type[], typeSetKind: TypeFlags) { for (const type of types) { addTypeToSet(typeSet, type, typeSetKind); } @@ -4785,21 +4797,22 @@ namespace ts { if (types.length === 0) { return emptyUnionType; } - const typeSet: Type[] = []; + const typeSet = [] as TypeSet; addTypesToSet(typeSet, types, TypeFlags.Union); - if (containsTypeAny(typeSet)) { + if (typeSet.containsAny) { return anyType; } - if (noSubtypeReduction) { - if (!strictNullChecks) { - removeAllButLast(typeSet, undefinedType); - removeAllButLast(typeSet, nullType); - } + if (strictNullChecks) { + if (typeSet.containsNull) typeSet.push(nullType); + if (typeSet.containsUndefined) typeSet.push(undefinedType); } - else { + if (!noSubtypeReduction) { removeSubtypes(typeSet); } - if (typeSet.length === 1) { + if (typeSet.length === 0) { + return typeSet.containsNull ? nullType : undefinedType; + } + else if (typeSet.length === 1) { return typeSet[0]; } const id = getTypeListId(typeSet); @@ -4829,11 +4842,15 @@ namespace ts { if (types.length === 0) { return emptyObjectType; } - const typeSet: Type[] = []; + const typeSet = [] as TypeSet; addTypesToSet(typeSet, types, TypeFlags.Intersection); - if (containsTypeAny(typeSet)) { + if (typeSet.containsAny) { return anyType; } + if (strictNullChecks) { + if (typeSet.containsNull) typeSet.push(nullType); + if (typeSet.containsUndefined) typeSet.push(undefinedType); + } if (typeSet.length === 1) { return typeSet[0]; } From 1302418776efba8d57bfe771e95597c9b2a3f123 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 4 Mar 2016 10:43:10 -0800 Subject: [PATCH 091/274] Accepting new baselines --- tests/baselines/reference/arrayLiterals2ES5.types | 2 +- .../reference/destructuringVariableDeclaration1ES5.types | 4 ++-- .../reference/destructuringVariableDeclaration1ES6.types | 4 ++-- .../baselines/reference/logicalAndOperatorWithEveryType.types | 2 +- .../baselines/reference/logicalOrOperatorWithEveryType.types | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/baselines/reference/arrayLiterals2ES5.types b/tests/baselines/reference/arrayLiterals2ES5.types index cbfb620fb00..a9cf31611c2 100644 --- a/tests/baselines/reference/arrayLiterals2ES5.types +++ b/tests/baselines/reference/arrayLiterals2ES5.types @@ -130,7 +130,7 @@ var temp2: [number[], string[]] = [[1, 2, 3], ["hello", "string"]]; var temp3 = [undefined, null, undefined]; >temp3 : any[] ->[undefined, null, undefined] : undefined[] +>[undefined, null, undefined] : null[] >undefined : undefined >null : null >undefined : undefined diff --git a/tests/baselines/reference/destructuringVariableDeclaration1ES5.types b/tests/baselines/reference/destructuringVariableDeclaration1ES5.types index aab01926a5a..f8188147a79 100644 --- a/tests/baselines/reference/destructuringVariableDeclaration1ES5.types +++ b/tests/baselines/reference/destructuringVariableDeclaration1ES5.types @@ -168,7 +168,7 @@ var {f: [f1, f2, { f3: f4, f5 }, , ]} = { f: [1, 2, { f3: 4, f5: 0 }] }; var {g: {g1 = [undefined, null]}}: { g: { g1: any[] } } = { g: { g1: [1, 2] } }; >g : any >g1 : any[] ->[undefined, null] : undefined[] +>[undefined, null] : null[] >undefined : undefined >null : null >g : { g1: any[]; } @@ -184,7 +184,7 @@ var {g: {g1 = [undefined, null]}}: { g: { g1: any[] } } = { g: { g1: [1, 2] } }; var {h: {h1 = [undefined, null]}}: { h: { h1: number[] } } = { h: { h1: [1, 2] } }; >h : any >h1 : number[] ->[undefined, null] : undefined[] +>[undefined, null] : null[] >undefined : undefined >null : null >h : { h1: number[]; } diff --git a/tests/baselines/reference/destructuringVariableDeclaration1ES6.types b/tests/baselines/reference/destructuringVariableDeclaration1ES6.types index 7e98817c052..7b4fe5409db 100644 --- a/tests/baselines/reference/destructuringVariableDeclaration1ES6.types +++ b/tests/baselines/reference/destructuringVariableDeclaration1ES6.types @@ -168,7 +168,7 @@ var {f: [f1, f2, { f3: f4, f5 }, , ]} = { f: [1, 2, { f3: 4, f5: 0 }] }; var {g: {g1 = [undefined, null]}}: { g: { g1: any[] } } = { g: { g1: [1, 2] } }; >g : any >g1 : any[] ->[undefined, null] : undefined[] +>[undefined, null] : null[] >undefined : undefined >null : null >g : { g1: any[]; } @@ -184,7 +184,7 @@ var {g: {g1 = [undefined, null]}}: { g: { g1: any[] } } = { g: { g1: [1, 2] } }; var {h: {h1 = [undefined, null]}}: { h: { h1: number[] } } = { h: { h1: [1, 2] } }; >h : any >h1 : number[] ->[undefined, null] : undefined[] +>[undefined, null] : null[] >undefined : undefined >null : null >h : { h1: number[]; } diff --git a/tests/baselines/reference/logicalAndOperatorWithEveryType.types b/tests/baselines/reference/logicalAndOperatorWithEveryType.types index bd913e94da5..b2628eed921 100644 --- a/tests/baselines/reference/logicalAndOperatorWithEveryType.types +++ b/tests/baselines/reference/logicalAndOperatorWithEveryType.types @@ -623,7 +623,7 @@ var rj8 = a8 && undefined; var rj9 = null && undefined; >rj9 : any ->null && undefined : undefined +>null && undefined : null >null : null >undefined : undefined diff --git a/tests/baselines/reference/logicalOrOperatorWithEveryType.types b/tests/baselines/reference/logicalOrOperatorWithEveryType.types index 609af4ecc94..4540e35aaf4 100644 --- a/tests/baselines/reference/logicalOrOperatorWithEveryType.types +++ b/tests/baselines/reference/logicalOrOperatorWithEveryType.types @@ -572,7 +572,7 @@ var rj9 = null || null; // null || null is any var rj10 = undefined || null; // undefined || null is any >rj10 : any ->undefined || null : undefined +>undefined || null : null >undefined : undefined >null : null From d6fcd1af1ba424eb163a0da153b4c296de825f7c Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 4 Mar 2016 13:19:58 -0800 Subject: [PATCH 092/274] Consider for-in and for-of variables to be definitely assigned --- src/compiler/checker.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1e693867baf..491e1fe0ee1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7525,6 +7525,10 @@ namespace ts { if (!declaration || declaration.kind !== SyntaxKind.VariableDeclaration || (declaration).initializer) { return; } + const parentParentKind = declaration.parent.parent.kind; + if (parentParentKind === SyntaxKind.ForOfStatement || parentParentKind === SyntaxKind.ForInStatement) { + return; + } const declarationContainer = getContainingFunction(declaration) || getSourceFileOfNode(declaration); const referenceContainer = getContainingFunction(reference) || getSourceFileOfNode(reference); if (declarationContainer !== referenceContainer) { From 15b240548f11eae650e736a34750373d301009c9 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 4 Mar 2016 15:01:11 -0800 Subject: [PATCH 093/274] Extract and lift nullability over best common supertype --- src/compiler/checker.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 491e1fe0ee1..ee9240f58e3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6286,14 +6286,22 @@ namespace ts { } function isSupertypeOfEach(candidate: Type, types: Type[]): boolean { - for (const type of types) { - if (candidate !== type && !isTypeSubtypeOf(type, candidate)) return false; + for (const t of types) { + if (candidate !== t && !isTypeSubtypeOf(t, candidate)) return false; } return true; } function getCommonSupertype(types: Type[]): Type { - return forEach(types, t => isSupertypeOfEach(t, types) ? t : undefined); + if (!strictNullChecks) { + return forEach(types, t => isSupertypeOfEach(t, types) ? t : undefined); + } + const primaryTypes = filter(types, t => !(t.flags & TypeFlags.Nullable)); + if (!primaryTypes.length) { + return getUnionType(types); + } + const supertype = forEach(primaryTypes, t => isSupertypeOfEach(t, primaryTypes) ? t : undefined); + return supertype && addNullableKind(supertype, reduceLeft(types, (flags, t) => flags | t.flags, 0) & TypeFlags.Nullable); } function reportNoCommonSupertypeError(types: Type[], errorLocation: Node, errorMessageChainHead: DiagnosticMessageChain): void { From 25a72d60852ea01f41e6869a848d97836dd22be1 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 4 Mar 2016 15:51:22 -0800 Subject: [PATCH 094/274] Removing unused functions --- src/compiler/checker.ts | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ee9240f58e3..666ed64b176 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4767,25 +4767,6 @@ namespace ts { } } - function containsTypeAny(types: Type[]): boolean { - for (const type of types) { - if (isTypeAny(type)) { - return true; - } - } - return false; - } - - function removeAllButLast(types: Type[], typeToRemove: Type) { - let i = types.length; - while (i > 0 && types.length > 1) { - i--; - if (types[i] === typeToRemove) { - types.splice(i, 1); - } - } - } - // We reduce the constituent type set to only include types that aren't subtypes of other types, unless // the noSubtypeReduction flag is specified, in which case we perform a simple deduplication based on // object identity. Subtype reduction is possible only when union types are known not to circularly From 64f572747cef63f96382d99090e2ed822f4d9267 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 4 Mar 2016 17:26:56 -0800 Subject: [PATCH 095/274] Introduce comparable (a.k.a. possibly assignable) relation --- src/compiler/checker.ts | 56 ++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 666ed64b176..15a57ed8931 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -229,6 +229,7 @@ namespace ts { const subtypeRelation: Map = {}; const assignableRelation: Map = {}; + const comparableRelation: Map = {}; const identityRelation: Map = {}; // This is for caching the result of getSymbolDisplayBuilder. Do not access directly. @@ -5267,6 +5268,10 @@ namespace ts { return checkTypeAssignableTo(source, target, /*errorNode*/ undefined); } + function isTypeComparableTo(source: Type, target: Type): boolean { + return checkTypeComparableTo(source, target, /*errorNode*/ undefined); + } + function checkTypeSubtypeOf(source: Type, target: Type, errorNode: Node, headMessage?: DiagnosticMessage, containingMessageChain?: DiagnosticMessageChain): boolean { return checkTypeRelatedTo(source, target, subtypeRelation, errorNode, headMessage, containingMessageChain); } @@ -5275,6 +5280,10 @@ namespace ts { return checkTypeRelatedTo(source, target, assignableRelation, errorNode, headMessage, containingMessageChain); } + function checkTypeComparableTo(source: Type, target: Type, errorNode: Node, headMessage?: DiagnosticMessage, containingMessageChain?: DiagnosticMessageChain): boolean { + return checkTypeRelatedTo(source, target, comparableRelation, errorNode, headMessage, containingMessageChain); + } + function isSignatureAssignableTo(source: Signature, target: Signature, ignoreReturnTypes: boolean): boolean { @@ -5432,7 +5441,7 @@ namespace ts { * Checks if 'source' is related to 'target' (e.g.: is a assignable to). * @param source The left-hand-side of the relation. * @param target The right-hand-side of the relation. - * @param relation The relation considered. One of 'identityRelation', 'assignableRelation', or 'subTypeRelation'. + * @param relation The relation considered. One of 'identityRelation', 'subtypeRelation', 'assignableRelation', or 'comparableRelation'. * Used as both to determine which checks are performed and as a cache of previously computed results. * @param errorNode The suggested node upon which all errors will be reported, if defined. This may or may not be the actual node used. * @param headMessage If the error chain should be prepended by a head message, then headMessage will be used. @@ -5510,7 +5519,7 @@ namespace ts { } } if (source.flags & TypeFlags.StringLiteral && target === stringType) return Ternary.True; - if (relation === assignableRelation) { + if (relation === assignableRelation || relation === comparableRelation) { if (isTypeAny(source)) return Ternary.True; if (source === numberType && target.flags & TypeFlags.Enum) return Ternary.True; } @@ -5538,8 +5547,15 @@ namespace ts { // Note that the "each" checks must precede the "some" checks to produce the correct results if (source.flags & TypeFlags.Union) { - if (result = eachTypeRelatedToType(source, target, reportErrors)) { - return result; + if (relation === comparableRelation) { + if (result = someTypeRelatedToType(source, target, reportErrors)) { + return result; + } + } + else { + if (result = eachTypeRelatedToType(source, target, reportErrors)) { + return result; + } } } else if (target.flags & TypeFlags.Intersection) { @@ -5634,7 +5650,8 @@ namespace ts { function isKnownProperty(type: Type, name: string): boolean { if (type.flags & TypeFlags.ObjectType) { const resolved = resolveStructuredTypeMembers(type); - if (relation === assignableRelation && (type === globalObjectType || resolved.properties.length === 0) || + if ((relation === assignableRelation || relation === comparableRelation) && + (type === globalObjectType || resolved.properties.length === 0) || resolved.stringIndexInfo || resolved.numberIndexInfo || getPropertyOfType(type, name)) { return true; } @@ -10774,12 +10791,8 @@ namespace ts { const targetType = getTypeFromTypeNode(node.type); if (produceDiagnostics && targetType !== unknownType) { const widenedType = getWidenedType(exprType); - - // Permit 'number[] | "foo"' to be asserted to 'string'. - const bothAreStringLike = maybeTypeOfKind(targetType, TypeFlags.StringLike) && - maybeTypeOfKind(widenedType, TypeFlags.StringLike); - if (!bothAreStringLike && !(isTypeAssignableTo(targetType, widenedType))) { - checkTypeAssignableTo(exprType, targetType, node, Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other); + if (!isTypeComparableTo(targetType, widenedType)) { + checkTypeComparableTo(exprType, targetType, node, Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other); } } return targetType; @@ -11649,11 +11662,7 @@ namespace ts { case SyntaxKind.ExclamationEqualsToken: case SyntaxKind.EqualsEqualsEqualsToken: case SyntaxKind.ExclamationEqualsEqualsToken: - // Permit 'number[] | "foo"' to be asserted to 'string'. - if (maybeTypeOfKind(leftType, TypeFlags.StringLike) && maybeTypeOfKind(rightType, TypeFlags.StringLike)) { - return booleanType; - } - if (!isTypeAssignableTo(leftType, rightType) && !isTypeAssignableTo(rightType, leftType)) { + if (!isTypeComparableTo(leftType, rightType) && !isTypeComparableTo(rightType, leftType)) { reportOperatorError(); } return booleanType; @@ -14180,17 +14189,12 @@ namespace ts { if (produceDiagnostics && clause.kind === SyntaxKind.CaseClause) { const caseClause = clause; // TypeScript 1.0 spec (April 2014):5.9 - // In a 'switch' statement, each 'case' expression must be of a type that is assignable to or from the type of the 'switch' expression. + // In a 'switch' statement, each 'case' expression must be of a type that is comparable + // to or from the type of the 'switch' expression. const caseType = checkExpression(caseClause.expression); - - const expressionTypeIsAssignableToCaseType = - // Permit 'number[] | "foo"' to be asserted to 'string'. - (expressionTypeIsStringLike && maybeTypeOfKind(caseType, TypeFlags.StringLike)) || - isTypeAssignableTo(expressionType, caseType); - - if (!expressionTypeIsAssignableToCaseType) { - // 'expressionType is not assignable to caseType', try the reversed check and report errors if it fails - checkTypeAssignableTo(caseType, expressionType, caseClause.expression, /*headMessage*/ undefined); + if (!isTypeComparableTo(expressionType, caseType)) { + // expressionType is not comparable to caseType, try the reversed check and report errors if it fails + checkTypeComparableTo(caseType, expressionType, caseClause.expression, /*headMessage*/ undefined); } } forEach(clause.statements, checkSourceElement); From 436e70ea8f27993ece5ea625168a9304218dad9a Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 4 Mar 2016 17:27:42 -0800 Subject: [PATCH 096/274] Accepting new baselines --- .../reference/castingTuple.errors.txt | 23 +------------------ ...eralTypesWithVariousOperators02.errors.txt | 13 +++++++++-- 2 files changed, 12 insertions(+), 24 deletions(-) diff --git a/tests/baselines/reference/castingTuple.errors.txt b/tests/baselines/reference/castingTuple.errors.txt index 62a36c9c156..128ee5b5bb4 100644 --- a/tests/baselines/reference/castingTuple.errors.txt +++ b/tests/baselines/reference/castingTuple.errors.txt @@ -1,7 +1,3 @@ -tests/cases/conformance/types/tuple/castingTuple.ts(13,23): error TS2352: Neither type '[number, string]' nor type '[number, string, boolean]' is assignable to the other. - Property '2' is missing in type '[number, string]'. -tests/cases/conformance/types/tuple/castingTuple.ts(16,21): error TS2352: Neither type '[C, D]' nor type '[C, D, A]' is assignable to the other. - Property '2' is missing in type '[C, D]'. tests/cases/conformance/types/tuple/castingTuple.ts(28,10): error TS2352: Neither type '[number, string]' nor type '[number, number]' is assignable to the other. Types of property '1' are incompatible. Type 'string' is not assignable to type 'number'. @@ -10,15 +6,10 @@ tests/cases/conformance/types/tuple/castingTuple.ts(29,10): error TS2352: Neithe Type 'C' is not assignable to type 'A'. Property 'a' is missing in type 'C'. tests/cases/conformance/types/tuple/castingTuple.ts(30,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'array1' must be of type '{}[]', but here has type 'number[]'. -tests/cases/conformance/types/tuple/castingTuple.ts(30,14): error TS2352: Neither type '[number, string]' nor type 'number[]' is assignable to the other. - Types of property 'pop' are incompatible. - Type '() => number | string' is not assignable to type '() => number'. - Type 'number | string' is not assignable to type 'number'. - Type 'string' is not assignable to type 'number'. tests/cases/conformance/types/tuple/castingTuple.ts(31,1): error TS2304: Cannot find name 't4'. -==== tests/cases/conformance/types/tuple/castingTuple.ts (7 errors) ==== +==== tests/cases/conformance/types/tuple/castingTuple.ts (4 errors) ==== interface I { } class A { a = 10; } class C implements I { c }; @@ -32,15 +23,9 @@ tests/cases/conformance/types/tuple/castingTuple.ts(31,1): error TS2304: Cannot var numStrTuple: [number, string] = [5, "foo"]; var emptyObjTuple = <[{}, {}]>numStrTuple; var numStrBoolTuple = <[number, string, boolean]>numStrTuple; - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2352: Neither type '[number, string]' nor type '[number, string, boolean]' is assignable to the other. -!!! error TS2352: Property '2' is missing in type '[number, string]'. var classCDTuple: [C, D] = [new C(), new D()]; var interfaceIITuple = <[I, I]>classCDTuple; var classCDATuple = <[C, D, A]>classCDTuple; - ~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2352: Neither type '[C, D]' nor type '[C, D, A]' is assignable to the other. -!!! error TS2352: Property '2' is missing in type '[C, D]'. var eleFromCDA1 = classCDATuple[2]; // A var eleFromCDA2 = classCDATuple[5]; // C | D | A var t10: [E1, E2] = [E1.one, E2.one]; @@ -66,12 +51,6 @@ tests/cases/conformance/types/tuple/castingTuple.ts(31,1): error TS2304: Cannot var array1 = numStrTuple; ~~~~~~ !!! error TS2403: Subsequent variable declarations must have the same type. Variable 'array1' must be of type '{}[]', but here has type 'number[]'. - ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2352: Neither type '[number, string]' nor type 'number[]' is assignable to the other. -!!! error TS2352: Types of property 'pop' are incompatible. -!!! error TS2352: Type '() => number | string' is not assignable to type '() => number'. -!!! error TS2352: Type 'number | string' is not assignable to type 'number'. -!!! error TS2352: Type 'string' is not assignable to type 'number'. t4[2] = 10; ~~ !!! error TS2304: Cannot find name 't4'. diff --git a/tests/baselines/reference/stringLiteralTypesWithVariousOperators02.errors.txt b/tests/baselines/reference/stringLiteralTypesWithVariousOperators02.errors.txt index 69dd6c2f6a9..92afe67df0c 100644 --- a/tests/baselines/reference/stringLiteralTypesWithVariousOperators02.errors.txt +++ b/tests/baselines/reference/stringLiteralTypesWithVariousOperators02.errors.txt @@ -7,9 +7,12 @@ tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperato tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperators02.ts(13,11): error TS2356: An arithmetic operand must be of type 'any', 'number' or an enum type. tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperators02.ts(14,9): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperators02.ts(15,9): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. +tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperators02.ts(16,9): error TS2365: Operator '<' cannot be applied to types '"ABC"' and '"XYZ"'. +tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperators02.ts(17,9): error TS2365: Operator '===' cannot be applied to types '"ABC"' and '"XYZ"'. +tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperators02.ts(18,9): error TS2365: Operator '!=' cannot be applied to types '"ABC"' and '"XYZ"'. -==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperators02.ts (9 errors) ==== +==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperators02.ts (12 errors) ==== let abc: "ABC" = "ABC"; let xyz: "XYZ" = "XYZ"; @@ -44,5 +47,11 @@ tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperato ~~~~~~~~~~~~~~~~ !!! error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. let j = abc < xyz; + ~~~~~~~~~ +!!! error TS2365: Operator '<' cannot be applied to types '"ABC"' and '"XYZ"'. let k = abc === xyz; - let l = abc != xyz; \ No newline at end of file + ~~~~~~~~~~~ +!!! error TS2365: Operator '===' cannot be applied to types '"ABC"' and '"XYZ"'. + let l = abc != xyz; + ~~~~~~~~~~ +!!! error TS2365: Operator '!=' cannot be applied to types '"ABC"' and '"XYZ"'. \ No newline at end of file From a0790fba7df3ee2109282a56d2635bfd3a09c35c Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 4 Mar 2016 17:39:56 -0800 Subject: [PATCH 097/274] Add only 'undefined' to optional parameter types --- src/compiler/checker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 15a57ed8931..9384145164e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2698,7 +2698,7 @@ namespace ts { // Use type from type annotation if one is present if (declaration.type) { const type = getTypeFromTypeNode(declaration.type); - return declaration.questionToken ? getNullableType(type) : type; + return strictNullChecks && declaration.questionToken ? addNullableKind(type, TypeFlags.Undefined) : type; } if (declaration.kind === SyntaxKind.Parameter) { @@ -2713,7 +2713,7 @@ namespace ts { // Use contextual parameter type if one is available const type = getContextuallyTypedParameterType(declaration); if (type) { - return declaration.questionToken ? getNullableType(type) : type; + return strictNullChecks && declaration.questionToken ? addNullableKind(type, TypeFlags.Undefined) : type; } } From eed4093be500b50d659bcd8efd97f588c3df13b9 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 5 Mar 2016 09:56:01 -0800 Subject: [PATCH 098/274] Fix bugs in reduceLeft and reduceRight --- src/compiler/core.ts | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 702ded96a3f..5e4aaf89aa1 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -242,11 +242,9 @@ namespace ts { const count = array.length; if (count > 0) { let pos = 0; - let result = arguments.length <= 2 ? array[pos] : initial; - pos++; + let result = arguments.length <= 2 ? array[pos++] : initial; while (pos < count) { - result = f(result, array[pos]); - pos++; + result = f(result, array[pos++]); } return result; } @@ -260,11 +258,9 @@ namespace ts { if (array) { let pos = array.length - 1; if (pos >= 0) { - let result = arguments.length <= 2 ? array[pos] : initial; - pos--; + let result = arguments.length <= 2 ? array[pos--] : initial; while (pos >= 0) { - result = f(result, array[pos]); - pos--; + result = f(result, array[pos--]); } return result; } From 2762772afd6ad6d5bc8981e833bb15db815da069 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 5 Mar 2016 09:58:47 -0800 Subject: [PATCH 099/274] Include 'undefined' in return type for implicit or expressionless returns --- src/compiler/checker.ts | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9384145164e..e269dc380ca 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6290,6 +6290,14 @@ namespace ts { return true; } + function getCombinedFlagsOfTypes(types: Type[]) { + let flags: TypeFlags = 0; + for (const t of types) { + flags |= t.flags; + } + return flags; + } + function getCommonSupertype(types: Type[]): Type { if (!strictNullChecks) { return forEach(types, t => isSupertypeOfEach(t, types) ? t : undefined); @@ -6299,7 +6307,7 @@ namespace ts { return getUnionType(types); } const supertype = forEach(primaryTypes, t => isSupertypeOfEach(t, primaryTypes) ? t : undefined); - return supertype && addNullableKind(supertype, reduceLeft(types, (flags, t) => flags | t.flags, 0) & TypeFlags.Nullable); + return supertype && addNullableKind(supertype, getCombinedFlagsOfTypes(types) & TypeFlags.Nullable); } function reportNoCommonSupertypeError(types: Type[], errorLocation: Node, errorMessageChainHead: DiagnosticMessageChain): void { @@ -10931,7 +10939,8 @@ namespace ts { } } else { - types = checkAndAggregateReturnExpressionTypes(func.body, contextualMapper, isAsync); + const hasImplicitReturn = !!(func.flags & NodeFlags.HasImplicitReturn); + types = checkAndAggregateReturnExpressionTypes(func.body, contextualMapper, isAsync, hasImplicitReturn); if (types.length === 0) { if (isAsync) { // For an async function, the return type will not be void, but rather a Promise for void. @@ -11011,9 +11020,9 @@ namespace ts { return aggregatedTypes; } - function checkAndAggregateReturnExpressionTypes(body: Block, contextualMapper?: TypeMapper, isAsync?: boolean): Type[] { + function checkAndAggregateReturnExpressionTypes(body: Block, contextualMapper: TypeMapper, isAsync: boolean, hasImplicitReturn: boolean): Type[] { const aggregatedTypes: Type[] = []; - + let hasOmittedExpressions = false; forEachReturnStatement(body, returnStatement => { const expr = returnStatement.expression; if (expr) { @@ -11025,13 +11034,19 @@ namespace ts { // the native Promise type by the caller. type = checkAwaitedType(type, body.parent, Diagnostics.Return_expression_in_async_function_does_not_have_a_valid_callable_then_member); } - if (!contains(aggregatedTypes, type)) { aggregatedTypes.push(type); } } + else { + hasOmittedExpressions = true; + } }); - + if (strictNullChecks && aggregatedTypes.length && (hasOmittedExpressions || hasImplicitReturn)) { + if (!contains(aggregatedTypes, undefinedType)) { + aggregatedTypes.push(undefinedType); + } + } return aggregatedTypes; } From 097f4564bb06a7a73b71b95cba18f1e6dce54d44 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 5 Mar 2016 10:07:28 -0800 Subject: [PATCH 100/274] Remove unused variable --- src/compiler/checker.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e269dc380ca..5cfdc6bc104 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14185,7 +14185,6 @@ namespace ts { let hasDuplicateDefaultClause = false; const expressionType = checkExpression(node.expression); - const expressionTypeIsStringLike = maybeTypeOfKind(expressionType, TypeFlags.StringLike); forEach(node.caseBlock.clauses, clause => { // Grammar check for duplicate default clauses, skip if we already report duplicate default clause if (clause.kind === SyntaxKind.DefaultClause && !hasDuplicateDefaultClause) { From 689e28d3aca1b4ac91cd419a23d03b5650ab6a10 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 5 Mar 2016 11:14:57 -0800 Subject: [PATCH 101/274] Keep linter happy with fix in reduceLeft/reduceRight --- src/compiler/core.ts | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 5e4aaf89aa1..362d0834cd8 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -242,9 +242,17 @@ namespace ts { const count = array.length; if (count > 0) { let pos = 0; - let result = arguments.length <= 2 ? array[pos++] : initial; + let result: T | U; + if (arguments.length <= 2) { + result = array[pos]; + pos++; + } + else { + result = initial; + } while (pos < count) { - result = f(result, array[pos++]); + result = f(result, array[pos]); + pos++; } return result; } @@ -258,9 +266,17 @@ namespace ts { if (array) { let pos = array.length - 1; if (pos >= 0) { - let result = arguments.length <= 2 ? array[pos--] : initial; + let result: T | U; + if (arguments.length <= 2) { + result = array[pos]; + pos--; + } + else { + result = initial; + } while (pos >= 0) { - result = f(result, array[pos--]); + result = f(result, array[pos]); + pos--; } return result; } From 8db7af035d2406bed79cd29d3d7257fa8479f374 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 5 Mar 2016 11:16:31 -0800 Subject: [PATCH 102/274] Proper handling of 'null' and 'undefined' in equals and not equals guards --- src/compiler/checker.ts | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5cfdc6bc104..d90c8a740f4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6388,6 +6388,11 @@ namespace ts { return flags & TypeFlags.Nullable; } + function getNullableTypeOfKind(kind: TypeFlags) { + return kind & TypeFlags.Null ? kind & TypeFlags.Undefined ? + getUnionType([nullType, undefinedType]) : nullType : undefinedType; + } + function isNullableType(type: Type) { return getNullableKind(type) === TypeFlags.Nullable; } @@ -7216,12 +7221,11 @@ namespace ts { switch (expr.operatorToken.kind) { case SyntaxKind.EqualsEqualsToken: case SyntaxKind.ExclamationEqualsToken: + case SyntaxKind.EqualsEqualsEqualsToken: + case SyntaxKind.ExclamationEqualsEqualsToken: if (isNullOrUndefinedLiteral(expr.right)) { return narrowTypeByNullCheck(type, expr, assumeTrue); } - // Fall through - case SyntaxKind.EqualsEqualsEqualsToken: - case SyntaxKind.ExclamationEqualsEqualsToken: if (expr.left.kind === SyntaxKind.TypeOfExpression && expr.right.kind === SyntaxKind.StringLiteral) { return narrowTypeByTypeof(type, expr, assumeTrue); } @@ -7237,14 +7241,22 @@ namespace ts { } function narrowTypeByNullCheck(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { - // We have '==' or '!=' operator with 'null' or 'undefined' on the right - if (expr.operatorToken.kind === SyntaxKind.ExclamationEqualsToken) { + // We have '==', '!=', '===', or '!==' operator with 'null' or 'undefined' on the right + const operator = expr.operatorToken.kind; + if (operator === SyntaxKind.ExclamationEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) { assumeTrue = !assumeTrue; } - if (!strictNullChecks || assumeTrue || !isMatchingReference(expr.left, reference)) { + if (!strictNullChecks || !isMatchingReference(expr.left, reference)) { return type; } - return getNonNullableType(type); + const doubleEquals = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsToken; + const exprNullableKind = doubleEquals ? TypeFlags.Nullable : + expr.right.kind === SyntaxKind.NullKeyword ? TypeFlags.Null : TypeFlags.Undefined; + if (assumeTrue) { + const nullableKind = getNullableKind(type) & exprNullableKind; + return nullableKind ? getNullableTypeOfKind(nullableKind) : type; + } + return removeNullableKind(type, exprNullableKind); } function narrowTypeByTypeof(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { From d0e4b4ae35215b2e288c96cc17d0d0e1b902898a Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 5 Mar 2016 15:23:00 -0800 Subject: [PATCH 103/274] Treat 'return' as 'return undefined' for type checking purposes --- src/compiler/checker.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d90c8a740f4..6d09cbffce8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14135,12 +14135,12 @@ namespace ts { } } - if (node.expression) { + if (strictNullChecks || node.expression) { const func = getContainingFunction(node); if (func) { const signature = getSignatureFromDeclaration(func); const returnType = getReturnTypeOfSignature(signature); - const exprType = checkExpressionCached(node.expression); + const exprType = node.expression ? checkExpressionCached(node.expression) : undefinedType; if (func.asteriskToken) { // A generator does not need its return expressions checked against its return type. @@ -14151,26 +14151,28 @@ namespace ts { } if (func.kind === SyntaxKind.SetAccessor) { - error(node.expression, Diagnostics.Setters_cannot_return_a_value); + if (node.expression) { + error(node.expression, Diagnostics.Setters_cannot_return_a_value); + } } else if (func.kind === SyntaxKind.Constructor) { - if (!checkTypeAssignableTo(exprType, returnType, node.expression)) { + if (node.expression && !checkTypeAssignableTo(exprType, returnType, node.expression)) { error(node.expression, Diagnostics.Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class); } } else if (func.type || isGetAccessorWithAnnotatedSetAccessor(func)) { if (isAsyncFunctionLike(func)) { const promisedType = getPromisedType(returnType); - const awaitedType = checkAwaitedType(exprType, node.expression, Diagnostics.Return_expression_in_async_function_does_not_have_a_valid_callable_then_member); + const awaitedType = checkAwaitedType(exprType, node.expression || node, Diagnostics.Return_expression_in_async_function_does_not_have_a_valid_callable_then_member); if (promisedType) { // If the function has a return type, but promisedType is // undefined, an error will be reported in checkAsyncFunctionReturnType // so we don't need to report one here. - checkTypeAssignableTo(awaitedType, promisedType, node.expression); + checkTypeAssignableTo(awaitedType, promisedType, node.expression || node); } } else { - checkTypeAssignableTo(exprType, returnType, node.expression); + checkTypeAssignableTo(exprType, returnType, node.expression || node); } } } From 129a4f190808ee3bda05fa76e32d1d92d8f667aa Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 5 Mar 2016 16:16:19 -0800 Subject: [PATCH 104/274] Check return type includes 'undefined' in function with implicit return --- src/compiler/checker.ts | 3 +++ src/compiler/diagnosticMessages.json | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6d09cbffce8..f15af886c36 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11095,6 +11095,9 @@ namespace ts { // NOTE: having returnType !== undefined is a precondition for entering this branch so func.type will always be present error(func.type, Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value); } + else if (returnType && strictNullChecks && !isTypeAssignableTo(undefinedType, returnType)) { + error(func.type, Diagnostics.Function_lacks_ending_return_statement_and_return_type_does_not_include_undefined); + } else if (compilerOptions.noImplicitReturns) { if (!returnType) { // If return type annotation is omitted check if function has any explicit return statements. diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 0b70ab98ce7..bd8701d9cea 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1091,6 +1091,10 @@ "category": "Error", "code": 2365 }, + "Function lacks ending return statement and return type does not include 'undefined'.": { + "category": "Error", + "code": 2366 + }, "Type parameter name cannot be '{0}'": { "category": "Error", "code": 2368 From 50d874e09d88a2f6948d246b25be7b5f2eea5810 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 5 Mar 2016 16:55:54 -0800 Subject: [PATCH 105/274] Improve type relationship error reporting for nullable types --- src/compiler/checker.ts | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f15af886c36..853ca8d07be 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5701,7 +5701,19 @@ namespace ts { function typeRelatedToSomeType(source: Type, target: UnionOrIntersectionType, reportErrors: boolean): Ternary { const targetTypes = target.types; - for (let i = 0, len = targetTypes.length; i < len; i++) { + let len = targetTypes.length; + // The null and undefined types are guaranteed to be at the end of the constituent type list. In order + // to produce the best possible errors we first check the nullable types, such that the last type we + // check and report errors from is a non-nullable type if one is present. + while (len >= 2 && targetTypes[len - 1].flags & TypeFlags.Nullable) { + const related = isRelatedTo(source, targetTypes[len - 1], /*reportErrors*/ false); + if (related) { + return related; + } + len--; + } + // Now check the non-nullable types and report errors on the last one. + for (let i = 0; i < len; i++) { const related = isRelatedTo(source, targetTypes[i], reportErrors && i === len - 1); if (related) { return related; @@ -5725,7 +5737,19 @@ namespace ts { function someTypeRelatedToType(source: UnionOrIntersectionType, target: Type, reportErrors: boolean): Ternary { const sourceTypes = source.types; - for (let i = 0, len = sourceTypes.length; i < len; i++) { + let len = sourceTypes.length; + // The null and undefined types are guaranteed to be at the end of the constituent type list. In order + // to produce the best possible errors we first check the nullable types, such that the last type we + // check and report errors from is a non-nullable type if one is present. + while (len >= 2 && sourceTypes[len - 1].flags & TypeFlags.Nullable) { + const related = isRelatedTo(sourceTypes[len - 1], target, /*reportErrors*/ false); + if (related) { + return related; + } + len--; + } + // Now check the non-nullable types and report errors on the last one. + for (let i = 0; i < len; i++) { const related = isRelatedTo(sourceTypes[i], target, reportErrors && i === len - 1); if (related) { return related; From 0a25bb58a4e2cdbe20cb0b38cef5f58920c8264c Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 6 Mar 2016 13:59:09 -0800 Subject: [PATCH 106/274] Make 'undefined' assignable to 'void' --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 853ca8d07be..9d05bc60c27 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5507,7 +5507,7 @@ namespace ts { if (isTypeAny(target)) return Ternary.True; if (source.flags & TypeFlags.Undefined) { - if (!strictNullChecks || target.flags & TypeFlags.Undefined || source === emptyArrayElementType) return Ternary.True; + if (!strictNullChecks || target.flags & (TypeFlags.Undefined | TypeFlags.Void) || source === emptyArrayElementType) return Ternary.True; } if (source.flags & TypeFlags.Null) { if (!strictNullChecks || target.flags & TypeFlags.Null) return Ternary.True; From 187eaaee7f37ffffb92fa398d280abb527be6fa2 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 7 Mar 2016 13:20:07 -0800 Subject: [PATCH 107/274] Fix issue with narrowing exported variables --- src/compiler/checker.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9d05bc60c27..f18239d5e74 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7165,12 +7165,11 @@ namespace ts { if (!leftmostIdentifier) { return type; } - const leftmostSymbol = getResolvedSymbol(leftmostIdentifier); - if (!(leftmostSymbol.flags & SymbolFlags.Variable)) { + const declaration = getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(leftmostIdentifier)).valueDeclaration; + if (!declaration || declaration.kind !== SyntaxKind.VariableDeclaration && declaration.kind !== SyntaxKind.Parameter && declaration.kind !== SyntaxKind.BindingElement) { return type; } - const declaration = getDeclarationOfKind(leftmostSymbol, SyntaxKind.VariableDeclaration); - const top = declaration && getDeclarationContainer(declaration); + const top = getDeclarationContainer(declaration); const originalType = type; const nodeStack: { node: Node, child: Node }[] = []; let node: Node = reference; From fbda0bdd94498d47cb4f5078565f2b6d1447e9c9 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 8 Mar 2016 11:46:47 -0800 Subject: [PATCH 108/274] Adding another check for undefined --- src/compiler/checker.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f18239d5e74..e2c57ffeaa1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7165,7 +7165,11 @@ namespace ts { if (!leftmostIdentifier) { return type; } - const declaration = getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(leftmostIdentifier)).valueDeclaration; + const leftmostSymbol = getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(leftmostIdentifier)); + if (!leftmostSymbol) { + return type; + } + const declaration = leftmostSymbol.valueDeclaration; if (!declaration || declaration.kind !== SyntaxKind.VariableDeclaration && declaration.kind !== SyntaxKind.Parameter && declaration.kind !== SyntaxKind.BindingElement) { return type; } From 868e53df2578c18fe62a6b3924e457442e7732e5 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 8 Mar 2016 11:47:18 -0800 Subject: [PATCH 109/274] Accepting new baselines --- .../typeGuardsInExternalModule.types | 8 ++--- .../reference/typeGuardsInModule.types | 30 +++++++++---------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/tests/baselines/reference/typeGuardsInExternalModule.types b/tests/baselines/reference/typeGuardsInExternalModule.types index e20063719f5..940e7db831a 100644 --- a/tests/baselines/reference/typeGuardsInExternalModule.types +++ b/tests/baselines/reference/typeGuardsInExternalModule.types @@ -44,13 +44,13 @@ if (typeof var2 === "string") { // export makes the var property and not variable strOrNum = var2; // string | number ->strOrNum = var2 : string | number +>strOrNum = var2 : string >strOrNum : string | number ->var2 : string | number +>var2 : string } else { strOrNum = var2; // number | string ->strOrNum = var2 : string | number +>strOrNum = var2 : number >strOrNum : string | number ->var2 : string | number +>var2 : number } diff --git a/tests/baselines/reference/typeGuardsInModule.types b/tests/baselines/reference/typeGuardsInModule.types index 6b6c552f0cc..7d3753037ad 100644 --- a/tests/baselines/reference/typeGuardsInModule.types +++ b/tests/baselines/reference/typeGuardsInModule.types @@ -64,15 +64,15 @@ module m1 { >"string" : string strOrNum = var3; // string | number ->strOrNum = var3 : string | number +>strOrNum = var3 : string >strOrNum : string | number ->var3 : string | number +>var3 : string } else { strOrNum = var3; // string | number ->strOrNum = var3 : string | number +>strOrNum = var3 : number >strOrNum : string | number ->var3 : string | number +>var3 : number } } // local module @@ -116,14 +116,14 @@ module m2 { // exported variable from outer the module strOrNum = typeof var3 === "string" && var3; // string | number ->strOrNum = typeof var3 === "string" && var3 : string | number +>strOrNum = typeof var3 === "string" && var3 : string >strOrNum : string | number ->typeof var3 === "string" && var3 : string | number +>typeof var3 === "string" && var3 : string >typeof var3 === "string" : boolean >typeof var3 : string >var3 : string | number >"string" : string ->var3 : string | number +>var3 : string // variables in module declaration var var4: string | number; @@ -160,15 +160,15 @@ module m2 { >"string" : string strOrNum = var5; // string | number ->strOrNum = var5 : string | number +>strOrNum = var5 : string >strOrNum : string | number ->var5 : string | number +>var5 : string } else { strOrNum = var5; // string | number ->strOrNum = var5 : string | number +>strOrNum = var5 : number >strOrNum : string | number ->var5 : string | number +>var5 : number } } } @@ -225,15 +225,15 @@ module m3.m4 { >"string" : string strOrNum = var3; // string | number ->strOrNum = var3 : string | number +>strOrNum = var3 : string >strOrNum : string | number ->var3 : string | number +>var3 : string } else { strOrNum = var3; // string | number ->strOrNum = var3 : string | number +>strOrNum = var3 : number >strOrNum : string | number ->var3 : string | number +>var3 : number } } From 482acccadaa754c96e09059dff68c50619e5f8aa Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 8 Mar 2016 13:05:00 -0800 Subject: [PATCH 110/274] Union this-types of unioned call signatures And and tests and baselines --- src/compiler/checker.ts | 26 +++++++++----- .../reference/unionThisTypeInFunctions.js | 18 ++++++++++ .../unionThisTypeInFunctions.symbols | 33 +++++++++++++++++ .../reference/unionThisTypeInFunctions.types | 35 +++++++++++++++++++ .../thisType/unionThisTypeInFunctions.ts | 12 +++++++ 5 files changed, 116 insertions(+), 8 deletions(-) create mode 100644 tests/baselines/reference/unionThisTypeInFunctions.js create mode 100644 tests/baselines/reference/unionThisTypeInFunctions.symbols create mode 100644 tests/baselines/reference/unionThisTypeInFunctions.types create mode 100644 tests/cases/conformance/types/thisType/unionThisTypeInFunctions.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d1b6dc5435e..b5337082c0f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3610,9 +3610,9 @@ namespace ts { setObjectTypeMembers(type, members, arrayType.callSignatures, arrayType.constructSignatures, arrayType.stringIndexInfo, arrayType.numberIndexInfo); } - function findMatchingSignature(signatureList: Signature[], signature: Signature, partialMatch: boolean, ignoreReturnTypes: boolean): Signature { + function findMatchingSignature(signatureList: Signature[], signature: Signature, partialMatch: boolean, ignoreThisTypes: boolean, ignoreReturnTypes: boolean): Signature { for (const s of signatureList) { - if (compareSignaturesIdentical(s, signature, partialMatch, ignoreReturnTypes, compareTypesIdentical)) { + if (compareSignaturesIdentical(s, signature, partialMatch, ignoreThisTypes, ignoreReturnTypes, compareTypesIdentical)) { return s; } } @@ -3626,7 +3626,7 @@ namespace ts { return undefined; } for (let i = 1; i < signatureLists.length; i++) { - if (!findMatchingSignature(signatureLists[i], signature, /*partialMatch*/ false, /*ignoreReturnTypes*/ false)) { + if (!findMatchingSignature(signatureLists[i], signature, /*partialMatch*/ false, /*ignoreThisTypes*/ false, /*ignoreReturnTypes*/ false)) { return undefined; } } @@ -3635,7 +3635,7 @@ namespace ts { let result: Signature[] = undefined; for (let i = 0; i < signatureLists.length; i++) { // Allow matching non-generic signatures to have excess parameters and different return types - const match = i === listIndex ? signature : findMatchingSignature(signatureLists[i], signature, /*partialMatch*/ true, /*ignoreReturnTypes*/ true); + const match = i === listIndex ? signature : findMatchingSignature(signatureLists[i], signature, /*partialMatch*/ true, /*ignoreThisTypes*/ true, /*ignoreReturnTypes*/ true); if (!match) { return undefined; } @@ -3656,13 +3656,16 @@ namespace ts { for (let i = 0; i < signatureLists.length; i++) { for (const signature of signatureLists[i]) { // Only process signatures with parameter lists that aren't already in the result list - if (!result || !findMatchingSignature(result, signature, /*partialMatch*/ false, /*ignoreReturnTypes*/ true)) { + if (!result || !findMatchingSignature(result, signature, /*partialMatch*/ false, /*ignoreThisTypes*/ true, /*ignoreReturnTypes*/ true)) { const unionSignatures = findMatchingSignatures(signatureLists, signature, i); if (unionSignatures) { let s = signature; // Union the result types when more than one signature matches if (unionSignatures.length > 1) { s = cloneSignature(signature); + if (forEach(unionSignatures, sig => sig.thisType)) { + s.thisType = getUnionType(map(unionSignatures, sig => sig.thisType || anyType)); + } // Clear resolved return type we possibly got from cloneSignature s.resolvedReturnType = undefined; s.unionSignatures = unionSignatures; @@ -6002,7 +6005,7 @@ namespace ts { } let result = Ternary.True; for (let i = 0, len = sourceSignatures.length; i < len; i++) { - const related = compareSignaturesIdentical(sourceSignatures[i], targetSignatures[i], /*partialMatch*/ false, /*ignoreReturnTypes*/ false, isRelatedTo); + const related = compareSignaturesIdentical(sourceSignatures[i], targetSignatures[i], /*partialMatch*/ false, /*ignoreThisTypes*/ false, /*ignoreReturnTypes*/ false, isRelatedTo); if (!related) { return Ternary.False; } @@ -6203,7 +6206,7 @@ namespace ts { /** * See signatureRelatedTo, compareSignaturesIdentical */ - function compareSignaturesIdentical(source: Signature, target: Signature, partialMatch: boolean, ignoreReturnTypes: boolean, compareTypes: (s: Type, t: Type) => Ternary): Ternary { + function compareSignaturesIdentical(source: Signature, target: Signature, partialMatch: boolean, ignoreThisTypes: boolean, ignoreReturnTypes: boolean, compareTypes: (s: Type, t: Type) => Ternary): Ternary { // TODO (drosen): De-duplicate code between related functions. if (source === target) { return Ternary.True; @@ -6224,6 +6227,13 @@ namespace ts { source = getErasedSignature(source); target = getErasedSignature(target); let result = Ternary.True; + if (!ignoreThisTypes && source.thisType && target.thisType) { + const related = compareTypes(source.thisType, target.thisType); + if (!related) { + return Ternary.False; + } + result &= related; + } const targetLen = target.parameters.length; for (let i = 0; i < targetLen; i++) { const s = isRestParameterIndex(source, i) ? getRestTypeOfSignature(source) : getTypeOfSymbol(source.parameters[i]); @@ -8137,7 +8147,7 @@ namespace ts { // This signature will contribute to contextual union signature signatureList = [signature]; } - else if (!compareSignaturesIdentical(signatureList[0], signature, /*partialMatch*/ false, /*ignoreReturnTypes*/ true, compareTypesIdentical)) { + else if (!compareSignaturesIdentical(signatureList[0], signature, /*partialMatch*/ false, /*ignoreThisTypes*/ true, /*ignoreReturnTypes*/ true, compareTypesIdentical)) { // Signatures aren't identical, do not use return undefined; } diff --git a/tests/baselines/reference/unionThisTypeInFunctions.js b/tests/baselines/reference/unionThisTypeInFunctions.js new file mode 100644 index 00000000000..31ff266087b --- /dev/null +++ b/tests/baselines/reference/unionThisTypeInFunctions.js @@ -0,0 +1,18 @@ +//// [unionThisTypeInFunctions.ts] +interface Real { + method(n: number): void; + data: string; +} +interface Fake { + method(n: number): void; + data: number; +} +function test(r: Real | Fake) { + r.method(12); +} + + +//// [unionThisTypeInFunctions.js] +function test(r) { + r.method(12); +} diff --git a/tests/baselines/reference/unionThisTypeInFunctions.symbols b/tests/baselines/reference/unionThisTypeInFunctions.symbols new file mode 100644 index 00000000000..8b5f2af01e0 --- /dev/null +++ b/tests/baselines/reference/unionThisTypeInFunctions.symbols @@ -0,0 +1,33 @@ +=== tests/cases/conformance/types/thisType/unionThisTypeInFunctions.ts === +interface Real { +>Real : Symbol(Real, Decl(unionThisTypeInFunctions.ts, 0, 0)) + + method(n: number): void; +>method : Symbol(method, Decl(unionThisTypeInFunctions.ts, 0, 16)) +>n : Symbol(n, Decl(unionThisTypeInFunctions.ts, 1, 11)) + + data: string; +>data : Symbol(data, Decl(unionThisTypeInFunctions.ts, 1, 28)) +} +interface Fake { +>Fake : Symbol(Fake, Decl(unionThisTypeInFunctions.ts, 3, 1)) + + method(n: number): void; +>method : Symbol(method, Decl(unionThisTypeInFunctions.ts, 4, 16)) +>n : Symbol(n, Decl(unionThisTypeInFunctions.ts, 5, 11)) + + data: number; +>data : Symbol(data, Decl(unionThisTypeInFunctions.ts, 5, 28)) +} +function test(r: Real | Fake) { +>test : Symbol(test, Decl(unionThisTypeInFunctions.ts, 7, 1)) +>r : Symbol(r, Decl(unionThisTypeInFunctions.ts, 8, 14)) +>Real : Symbol(Real, Decl(unionThisTypeInFunctions.ts, 0, 0)) +>Fake : Symbol(Fake, Decl(unionThisTypeInFunctions.ts, 3, 1)) + + r.method(12); +>r.method : Symbol(method, Decl(unionThisTypeInFunctions.ts, 0, 16), Decl(unionThisTypeInFunctions.ts, 4, 16)) +>r : Symbol(r, Decl(unionThisTypeInFunctions.ts, 8, 14)) +>method : Symbol(method, Decl(unionThisTypeInFunctions.ts, 0, 16), Decl(unionThisTypeInFunctions.ts, 4, 16)) +} + diff --git a/tests/baselines/reference/unionThisTypeInFunctions.types b/tests/baselines/reference/unionThisTypeInFunctions.types new file mode 100644 index 00000000000..f2c4f7ee4ec --- /dev/null +++ b/tests/baselines/reference/unionThisTypeInFunctions.types @@ -0,0 +1,35 @@ +=== tests/cases/conformance/types/thisType/unionThisTypeInFunctions.ts === +interface Real { +>Real : Real + + method(n: number): void; +>method : (this: this, n: number) => void +>n : number + + data: string; +>data : string +} +interface Fake { +>Fake : Fake + + method(n: number): void; +>method : (this: this, n: number) => void +>n : number + + data: number; +>data : number +} +function test(r: Real | Fake) { +>test : (this: void, r: Real | Fake) => void +>r : Real | Fake +>Real : Real +>Fake : Fake + + r.method(12); +>r.method(12) : void +>r.method : ((this: Real, n: number) => void) | ((this: Fake, n: number) => void) +>r : Real | Fake +>method : ((this: Real, n: number) => void) | ((this: Fake, n: number) => void) +>12 : number +} + diff --git a/tests/cases/conformance/types/thisType/unionThisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/unionThisTypeInFunctions.ts new file mode 100644 index 00000000000..a140c3fba95 --- /dev/null +++ b/tests/cases/conformance/types/thisType/unionThisTypeInFunctions.ts @@ -0,0 +1,12 @@ +// @strictThis: true +interface Real { + method(n: number): void; + data: string; +} +interface Fake { + method(n: number): void; + data: number; +} +function test(r: Real | Fake) { + r.method(12); +} From 7b531fcd05334c059a1eaa27c67807046a8bfeec Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 9 Mar 2016 13:06:06 -0800 Subject: [PATCH 111/274] Check this expressions in object literal methods Add a test and baseline --- src/compiler/checker.ts | 8 +++++++ .../reference/thisTypeInObjectLiterals.js | 16 ++++++++++++++ .../thisTypeInObjectLiterals.symbols | 19 +++++++++++++++++ .../reference/thisTypeInObjectLiterals.types | 21 +++++++++++++++++++ .../thisType/thisTypeInObjectLiterals.ts | 6 ++++++ 5 files changed, 70 insertions(+) create mode 100644 tests/baselines/reference/thisTypeInObjectLiterals.js create mode 100644 tests/baselines/reference/thisTypeInObjectLiterals.symbols create mode 100644 tests/baselines/reference/thisTypeInObjectLiterals.types create mode 100644 tests/cases/conformance/types/thisType/thisTypeInObjectLiterals.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b5337082c0f..7073af85fcf 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7494,6 +7494,14 @@ namespace ts { const symbol = getSymbolOfNode(container.parent); return container.flags & NodeFlags.Static ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol)).thisType; } + if (container.parent && container.parent.kind === SyntaxKind.ObjectLiteralExpression) { + // Note: this works because object literal methods are deferred, + // which means that the type of the containing object literal is already known. + const type = checkExpressionCached(container.parent); + if (type) { + return type; + } + } if (isInJavaScriptFile(node)) { const type = getTypeForThisExpressionFromJSDoc(container); diff --git a/tests/baselines/reference/thisTypeInObjectLiterals.js b/tests/baselines/reference/thisTypeInObjectLiterals.js new file mode 100644 index 00000000000..78854bf2388 --- /dev/null +++ b/tests/baselines/reference/thisTypeInObjectLiterals.js @@ -0,0 +1,16 @@ +//// [thisTypeInObjectLiterals.ts] +let o = { + d: "bar", + m() { + return this.d.length; + } +} + + +//// [thisTypeInObjectLiterals.js] +var o = { + d: "bar", + m: function () { + return this.d.length; + } +}; diff --git a/tests/baselines/reference/thisTypeInObjectLiterals.symbols b/tests/baselines/reference/thisTypeInObjectLiterals.symbols new file mode 100644 index 00000000000..6bea6d88c58 --- /dev/null +++ b/tests/baselines/reference/thisTypeInObjectLiterals.symbols @@ -0,0 +1,19 @@ +=== tests/cases/conformance/types/thisType/thisTypeInObjectLiterals.ts === +let o = { +>o : Symbol(o, Decl(thisTypeInObjectLiterals.ts, 0, 3)) + + d: "bar", +>d : Symbol(d, Decl(thisTypeInObjectLiterals.ts, 0, 9)) + + m() { +>m : Symbol(m, Decl(thisTypeInObjectLiterals.ts, 1, 13)) + + return this.d.length; +>this.d.length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>this.d : Symbol(d, Decl(thisTypeInObjectLiterals.ts, 0, 9)) +>this : Symbol(, Decl(thisTypeInObjectLiterals.ts, 0, 7)) +>d : Symbol(d, Decl(thisTypeInObjectLiterals.ts, 0, 9)) +>length : Symbol(String.length, Decl(lib.d.ts, --, --)) + } +} + diff --git a/tests/baselines/reference/thisTypeInObjectLiterals.types b/tests/baselines/reference/thisTypeInObjectLiterals.types new file mode 100644 index 00000000000..824b0b00f4c --- /dev/null +++ b/tests/baselines/reference/thisTypeInObjectLiterals.types @@ -0,0 +1,21 @@ +=== tests/cases/conformance/types/thisType/thisTypeInObjectLiterals.ts === +let o = { +>o : { d: string; m(): number; } +>{ d: "bar", m() { return this.d.length; }} : { d: string; m(): number; } + + d: "bar", +>d : string +>"bar" : string + + m() { +>m : () => number + + return this.d.length; +>this.d.length : number +>this.d : string +>this : { d: string; m(): number; } +>d : string +>length : number + } +} + diff --git a/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals.ts b/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals.ts new file mode 100644 index 00000000000..11c6b58d710 --- /dev/null +++ b/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals.ts @@ -0,0 +1,6 @@ +let o = { + d: "bar", + m() { + return this.d.length; + } +} From 4012587808d3027c88360c2f16e90075c2a32b90 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 9 Mar 2016 13:08:09 -0800 Subject: [PATCH 112/274] Update baselines: 'this' in object literal methods --- .../reference/commentsOnObjectLiteral3.symbols | 7 +++++++ .../reference/commentsOnObjectLiteral3.types | 12 ++++++------ .../baselines/reference/commentsOnObjectLiteral4.js | 7 ++++--- .../reference/commentsOnObjectLiteral4.symbols | 3 ++- .../reference/commentsOnObjectLiteral4.types | 9 ++++----- .../declFileObjectLiteralWithAccessors.symbols | 3 +++ .../declFileObjectLiteralWithAccessors.types | 6 +++--- .../declFileObjectLiteralWithOnlySetter.symbols | 3 +++ .../declFileObjectLiteralWithOnlySetter.types | 6 +++--- .../declarationEmitThisPredicates02.errors.txt | 7 ++++++- ...ionEmitThisPredicatesWithPrivateName02.errors.txt | 7 ++++++- ...xponentiationAssignmentWithIndexingOnLHS3.symbols | 7 +++++++ ...dExponentiationAssignmentWithIndexingOnLHS3.types | 12 ++++++------ .../reference/thisInObjectLiterals.errors.txt | 5 ++++- .../reference/throwInEnclosingStatements.symbols | 1 + .../reference/throwInEnclosingStatements.types | 2 +- tests/cases/compiler/commentsOnObjectLiteral4.ts | 4 ++-- .../expressions/thisKeyword/thisInObjectLiterals.ts | 2 +- 18 files changed, 69 insertions(+), 34 deletions(-) diff --git a/tests/baselines/reference/commentsOnObjectLiteral3.symbols b/tests/baselines/reference/commentsOnObjectLiteral3.symbols index 3d58fe2d6d7..81fa15b6a11 100644 --- a/tests/baselines/reference/commentsOnObjectLiteral3.symbols +++ b/tests/baselines/reference/commentsOnObjectLiteral3.symbols @@ -21,6 +21,10 @@ var v = { >a : Symbol(a, Decl(commentsOnObjectLiteral3.ts, 8, 13), Decl(commentsOnObjectLiteral3.ts, 12, 18)) return this.prop; +>this.prop : Symbol(prop, Decl(commentsOnObjectLiteral3.ts, 1, 9)) +>this : Symbol(, Decl(commentsOnObjectLiteral3.ts, 1, 7)) +>prop : Symbol(prop, Decl(commentsOnObjectLiteral3.ts, 1, 9)) + } /*trailing 1*/, //setter set a(value) { @@ -28,6 +32,9 @@ var v = { >value : Symbol(value, Decl(commentsOnObjectLiteral3.ts, 14, 7)) this.prop = value; +>this.prop : Symbol(prop, Decl(commentsOnObjectLiteral3.ts, 1, 9)) +>this : Symbol(, Decl(commentsOnObjectLiteral3.ts, 1, 7)) +>prop : Symbol(prop, Decl(commentsOnObjectLiteral3.ts, 1, 9)) >value : Symbol(value, Decl(commentsOnObjectLiteral3.ts, 14, 7)) } // trailing 2 diff --git a/tests/baselines/reference/commentsOnObjectLiteral3.types b/tests/baselines/reference/commentsOnObjectLiteral3.types index a63920fce0f..26a1e2e4250 100644 --- a/tests/baselines/reference/commentsOnObjectLiteral3.types +++ b/tests/baselines/reference/commentsOnObjectLiteral3.types @@ -24,9 +24,9 @@ var v = { >a : any return this.prop; ->this.prop : any ->this : any ->prop : any +>this.prop : number +>this : { prop: number; func: () => void; func1(): void; a: any; } +>prop : number } /*trailing 1*/, //setter @@ -36,9 +36,9 @@ var v = { this.prop = value; >this.prop = value : any ->this.prop : any ->this : any ->prop : any +>this.prop : number +>this : { prop: number; func: () => void; func1(): void; a: any; } +>prop : number >value : any } // trailing 2 diff --git a/tests/baselines/reference/commentsOnObjectLiteral4.js b/tests/baselines/reference/commentsOnObjectLiteral4.js index 3b7efefdff4..23e238b8307 100644 --- a/tests/baselines/reference/commentsOnObjectLiteral4.js +++ b/tests/baselines/reference/commentsOnObjectLiteral4.js @@ -5,9 +5,10 @@ var v = { * @type {number} */ get bar(): number { - return this._bar; + return 12; } -} +} + //// [commentsOnObjectLiteral4.js] var v = { @@ -15,6 +16,6 @@ var v = { * @type {number} */ get bar() { - return this._bar; + return 12; } }; diff --git a/tests/baselines/reference/commentsOnObjectLiteral4.symbols b/tests/baselines/reference/commentsOnObjectLiteral4.symbols index c1762cb75c8..568d6332126 100644 --- a/tests/baselines/reference/commentsOnObjectLiteral4.symbols +++ b/tests/baselines/reference/commentsOnObjectLiteral4.symbols @@ -9,6 +9,7 @@ var v = { get bar(): number { >bar : Symbol(bar, Decl(commentsOnObjectLiteral4.ts, 1, 9)) - return this._bar; + return 12; } } + diff --git a/tests/baselines/reference/commentsOnObjectLiteral4.types b/tests/baselines/reference/commentsOnObjectLiteral4.types index f458d73ae36..5d20d4f79cc 100644 --- a/tests/baselines/reference/commentsOnObjectLiteral4.types +++ b/tests/baselines/reference/commentsOnObjectLiteral4.types @@ -2,7 +2,7 @@ var v = { >v : { readonly bar: number; } ->{ /** * @type {number} */ get bar(): number { return this._bar; }} : { readonly bar: number; } +>{ /** * @type {number} */ get bar(): number { return 12; }} : { readonly bar: number; } /** * @type {number} @@ -10,9 +10,8 @@ var v = { get bar(): number { >bar : number - return this._bar; ->this._bar : any ->this : any ->_bar : any + return 12; +>12 : number } } + diff --git a/tests/baselines/reference/declFileObjectLiteralWithAccessors.symbols b/tests/baselines/reference/declFileObjectLiteralWithAccessors.symbols index 862b0b3781e..9b3599da674 100644 --- a/tests/baselines/reference/declFileObjectLiteralWithAccessors.symbols +++ b/tests/baselines/reference/declFileObjectLiteralWithAccessors.symbols @@ -15,6 +15,9 @@ function /*1*/makePoint(x: number) { set x(a: number) { this.b = a; } >x : Symbol(x, Decl(declFileObjectLiteralWithAccessors.ts, 3, 14), Decl(declFileObjectLiteralWithAccessors.ts, 4, 30)) >a : Symbol(a, Decl(declFileObjectLiteralWithAccessors.ts, 5, 14)) +>this.b : Symbol(b, Decl(declFileObjectLiteralWithAccessors.ts, 2, 12)) +>this : Symbol(, Decl(declFileObjectLiteralWithAccessors.ts, 2, 10)) +>b : Symbol(b, Decl(declFileObjectLiteralWithAccessors.ts, 2, 12)) >a : Symbol(a, Decl(declFileObjectLiteralWithAccessors.ts, 5, 14)) }; diff --git a/tests/baselines/reference/declFileObjectLiteralWithAccessors.types b/tests/baselines/reference/declFileObjectLiteralWithAccessors.types index f7bb57b0e1e..1bf012605c1 100644 --- a/tests/baselines/reference/declFileObjectLiteralWithAccessors.types +++ b/tests/baselines/reference/declFileObjectLiteralWithAccessors.types @@ -19,9 +19,9 @@ function /*1*/makePoint(x: number) { >x : number >a : number >this.b = a : number ->this.b : any ->this : any ->b : any +>this.b : number +>this : { b: number; x: number; } +>b : number >a : number }; diff --git a/tests/baselines/reference/declFileObjectLiteralWithOnlySetter.symbols b/tests/baselines/reference/declFileObjectLiteralWithOnlySetter.symbols index f7474466140..89b7b9dd747 100644 --- a/tests/baselines/reference/declFileObjectLiteralWithOnlySetter.symbols +++ b/tests/baselines/reference/declFileObjectLiteralWithOnlySetter.symbols @@ -11,6 +11,9 @@ function /*1*/makePoint(x: number) { set x(a: number) { this.b = a; } >x : Symbol(x, Decl(declFileObjectLiteralWithOnlySetter.ts, 3, 14)) >a : Symbol(a, Decl(declFileObjectLiteralWithOnlySetter.ts, 4, 14)) +>this.b : Symbol(b, Decl(declFileObjectLiteralWithOnlySetter.ts, 2, 12)) +>this : Symbol(, Decl(declFileObjectLiteralWithOnlySetter.ts, 2, 10)) +>b : Symbol(b, Decl(declFileObjectLiteralWithOnlySetter.ts, 2, 12)) >a : Symbol(a, Decl(declFileObjectLiteralWithOnlySetter.ts, 4, 14)) }; diff --git a/tests/baselines/reference/declFileObjectLiteralWithOnlySetter.types b/tests/baselines/reference/declFileObjectLiteralWithOnlySetter.types index 2b9b98a8963..1bce86915ad 100644 --- a/tests/baselines/reference/declFileObjectLiteralWithOnlySetter.types +++ b/tests/baselines/reference/declFileObjectLiteralWithOnlySetter.types @@ -15,9 +15,9 @@ function /*1*/makePoint(x: number) { >x : number >a : number >this.b = a : number ->this.b : any ->this : any ->b : any +>this.b : number +>this : { b: number; x: number; } +>b : number >a : number }; diff --git a/tests/baselines/reference/declarationEmitThisPredicates02.errors.txt b/tests/baselines/reference/declarationEmitThisPredicates02.errors.txt index 4d95cf01136..8cf85d4f764 100644 --- a/tests/baselines/reference/declarationEmitThisPredicates02.errors.txt +++ b/tests/baselines/reference/declarationEmitThisPredicates02.errors.txt @@ -1,7 +1,9 @@ tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicates02.ts(9,10): error TS2526: A 'this' type is available only in a non-static member of a class or interface. +tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicates02.ts(10,19): error TS2352: Neither type '{ m(): this is Foo; }' nor type 'Foo' is assignable to the other. + Property 'a' is missing in type '{ m(): this is Foo; }'. -==== tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicates02.ts (1 errors) ==== +==== tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicates02.ts (2 errors) ==== export interface Foo { a: string; @@ -14,6 +16,9 @@ tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredic ~~~~ !!! error TS2526: A 'this' type is available only in a non-static member of a class or interface. let dis = this as Foo; + ~~~~~~~~~~~ +!!! error TS2352: Neither type '{ m(): this is Foo; }' nor type 'Foo' is assignable to the other. +!!! error TS2352: Property 'a' is missing in type '{ m(): this is Foo; }'. return dis.a != null && dis.b != null && dis.c != null; } } \ No newline at end of file diff --git a/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.errors.txt b/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.errors.txt index 86c0f478133..0c0661023f5 100644 --- a/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.errors.txt +++ b/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.errors.txt @@ -1,8 +1,10 @@ tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicatesWithPrivateName02.ts(8,14): error TS4025: Exported variable 'obj' has or is using private name 'Foo'. tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicatesWithPrivateName02.ts(9,10): error TS2526: A 'this' type is available only in a non-static member of a class or interface. +tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicatesWithPrivateName02.ts(10,19): error TS2352: Neither type '{ m(): this is Foo; }' nor type 'Foo' is assignable to the other. + Property 'a' is missing in type '{ m(): this is Foo; }'. -==== tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicatesWithPrivateName02.ts (2 errors) ==== +==== tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicatesWithPrivateName02.ts (3 errors) ==== interface Foo { a: string; @@ -17,6 +19,9 @@ tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredic ~~~~ !!! error TS2526: A 'this' type is available only in a non-static member of a class or interface. let dis = this as Foo; + ~~~~~~~~~~~ +!!! error TS2352: Neither type '{ m(): this is Foo; }' nor type 'Foo' is assignable to the other. +!!! error TS2352: Property 'a' is missing in type '{ m(): this is Foo; }'. return dis.a != null && dis.b != null && dis.c != null; } } \ No newline at end of file diff --git a/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.symbols b/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.symbols index dbd5aa150dc..4da659c4a1a 100644 --- a/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.symbols +++ b/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.symbols @@ -8,11 +8,18 @@ var object = { get 0() { return this._0; +>this._0 : Symbol(_0, Decl(emitCompoundExponentiationAssignmentWithIndexingOnLHS3.ts, 1, 14)) +>this : Symbol(, Decl(emitCompoundExponentiationAssignmentWithIndexingOnLHS3.ts, 1, 12)) +>_0 : Symbol(_0, Decl(emitCompoundExponentiationAssignmentWithIndexingOnLHS3.ts, 1, 14)) + }, set 0(x: number) { >x : Symbol(x, Decl(emitCompoundExponentiationAssignmentWithIndexingOnLHS3.ts, 6, 10)) this._0 = x; +>this._0 : Symbol(_0, Decl(emitCompoundExponentiationAssignmentWithIndexingOnLHS3.ts, 1, 14)) +>this : Symbol(, Decl(emitCompoundExponentiationAssignmentWithIndexingOnLHS3.ts, 1, 12)) +>_0 : Symbol(_0, Decl(emitCompoundExponentiationAssignmentWithIndexingOnLHS3.ts, 1, 14)) >x : Symbol(x, Decl(emitCompoundExponentiationAssignmentWithIndexingOnLHS3.ts, 6, 10)) }, diff --git a/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.types b/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.types index 1877f391207..b47c88f3de3 100644 --- a/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.types +++ b/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.types @@ -10,9 +10,9 @@ var object = { get 0() { return this._0; ->this._0 : any ->this : any ->_0 : any +>this._0 : number +>this : { 0: number; _0: number; } +>_0 : number }, set 0(x: number) { @@ -20,9 +20,9 @@ var object = { this._0 = x; >this._0 = x : number ->this._0 : any ->this : any ->_0 : any +>this._0 : number +>this : { 0: number; _0: number; } +>_0 : number >x : number }, diff --git a/tests/baselines/reference/thisInObjectLiterals.errors.txt b/tests/baselines/reference/thisInObjectLiterals.errors.txt index 73300d86d74..f956ce42e34 100644 --- a/tests/baselines/reference/thisInObjectLiterals.errors.txt +++ b/tests/baselines/reference/thisInObjectLiterals.errors.txt @@ -1,7 +1,8 @@ tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts(7,13): error TS2403: Subsequent variable declarations must have the same type. Variable 't' must be of type '{ x: this; y: number; }', but here has type '{ x: MyClass; y: number; }'. +tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts(14,21): error TS2339: Property 'spaaace' does not exist on type '{ f(): any; }'. -==== tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts (1 errors) ==== +==== tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts (2 errors) ==== class MyClass { t: number; @@ -18,6 +19,8 @@ tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts(7,13): e var obj = { f() { return this.spaaace; + ~~~~~~~ +!!! error TS2339: Property 'spaaace' does not exist on type '{ f(): any; }'. } }; var obj: { f: () => any; }; diff --git a/tests/baselines/reference/throwInEnclosingStatements.symbols b/tests/baselines/reference/throwInEnclosingStatements.symbols index 42053c60efa..06fd9d53ff8 100644 --- a/tests/baselines/reference/throwInEnclosingStatements.symbols +++ b/tests/baselines/reference/throwInEnclosingStatements.symbols @@ -89,6 +89,7 @@ var aa = { >biz : Symbol(biz, Decl(throwInEnclosingStatements.ts, 41, 10)) throw this; +>this : Symbol(, Decl(throwInEnclosingStatements.ts, 40, 8)) } } diff --git a/tests/baselines/reference/throwInEnclosingStatements.types b/tests/baselines/reference/throwInEnclosingStatements.types index 32f0fb093bc..8add6e8b1a8 100644 --- a/tests/baselines/reference/throwInEnclosingStatements.types +++ b/tests/baselines/reference/throwInEnclosingStatements.types @@ -104,7 +104,7 @@ var aa = { >biz : () => void throw this; ->this : any +>this : { id: number; biz(): void; } } } diff --git a/tests/cases/compiler/commentsOnObjectLiteral4.ts b/tests/cases/compiler/commentsOnObjectLiteral4.ts index d685304f31e..dfb9e42b3cb 100644 --- a/tests/cases/compiler/commentsOnObjectLiteral4.ts +++ b/tests/cases/compiler/commentsOnObjectLiteral4.ts @@ -6,6 +6,6 @@ var v = { * @type {number} */ get bar(): number { - return this._bar; + return 12; } -} \ No newline at end of file +} diff --git a/tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts b/tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts index da38484bc07..ddfbb790980 100644 --- a/tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts +++ b/tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts @@ -8,7 +8,7 @@ class MyClass { } } -//type of 'this' in an object literal property of a function type is Any +//type of 'this' in an object literal method is the type of the object literal var obj = { f() { return this.spaaace; From 32978247bd1778136a2d83a87a2d6cf7fb729e09 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 9 Mar 2016 13:20:49 -0800 Subject: [PATCH 113/274] Add missed update of thisInObjectLiterals baseline --- tests/baselines/reference/thisInObjectLiterals.errors.txt | 2 +- tests/baselines/reference/thisInObjectLiterals.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/baselines/reference/thisInObjectLiterals.errors.txt b/tests/baselines/reference/thisInObjectLiterals.errors.txt index f956ce42e34..b0b1c63a34a 100644 --- a/tests/baselines/reference/thisInObjectLiterals.errors.txt +++ b/tests/baselines/reference/thisInObjectLiterals.errors.txt @@ -15,7 +15,7 @@ tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts(14,21): } } - //type of 'this' in an object literal property of a function type is Any + //type of 'this' in an object literal method is the type of the object literal var obj = { f() { return this.spaaace; diff --git a/tests/baselines/reference/thisInObjectLiterals.js b/tests/baselines/reference/thisInObjectLiterals.js index 4e71347a366..6c8380060a7 100644 --- a/tests/baselines/reference/thisInObjectLiterals.js +++ b/tests/baselines/reference/thisInObjectLiterals.js @@ -9,7 +9,7 @@ class MyClass { } } -//type of 'this' in an object literal property of a function type is Any +//type of 'this' in an object literal method is the type of the object literal var obj = { f() { return this.spaaace; @@ -29,7 +29,7 @@ var MyClass = (function () { }; return MyClass; }()); -//type of 'this' in an object literal property of a function type is Any +//type of 'this' in an object literal method is the type of the object literal var obj = { f: function () { return this.spaaace; From 3a46e72bde6f3fd8f9801022575f9024e95a9339 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 9 Mar 2016 13:40:17 -0800 Subject: [PATCH 114/274] After merge, update error numbers in baselines --- .../thisTypeInFunctionsNegative.errors.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt index fdb9489f639..c48ea11b3b0 100644 --- a/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt +++ b/tests/baselines/reference/thisTypeInFunctionsNegative.errors.txt @@ -91,10 +91,10 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(168,1): er tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(170,1): error TS2322: Type '(this: Base2) => number' is not assignable to type '(this: Base1) => number'. Types of parameters 'this' and 'this' are incompatible. Type 'Base1' is not assignable to type 'Base2'. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(179,16): error TS2672: A function that is called with the 'new' keyword cannot have a 'this' type that is void. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(180,24): error TS2672: A function that is called with the 'new' keyword cannot have a 'this' type that is void. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(184,17): error TS2674: A constructor cannot have a 'this' parameter. -tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(187,30): error TS2673: 'this' parameter must be the first parameter. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(179,16): error TS2678: A function that is called with the 'new' keyword cannot have a 'this' type that is void. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(180,24): error TS2678: A function that is called with the 'new' keyword cannot have a 'this' type that is void. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(184,17): error TS2680: A constructor cannot have a 'this' parameter. +tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(187,30): error TS2679: 'this' parameter must be the first parameter. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(187,61): error TS2339: Property 'n' does not exist on type 'void'. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(190,26): error TS1003: Identifier expected. tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(190,30): error TS1005: ',' expected. @@ -443,21 +443,21 @@ tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts(197,35): e } let voidThis = new VoidThis(); ~~~~~~~~~~~~~~ -!!! error TS2672: A function that is called with the 'new' keyword cannot have a 'this' type that is void. +!!! error TS2678: A function that is called with the 'new' keyword cannot have a 'this' type that is void. let implicitVoidThis = new ImplicitVoidThis(); ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2672: A function that is called with the 'new' keyword cannot have a 'this' type that is void. +!!! error TS2678: A function that is called with the 'new' keyword cannot have a 'this' type that is void. ///// syntax-ish errors ///// class ThisConstructor { constructor(this: ThisConstructor, private n: number) { ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2674: A constructor cannot have a 'this' parameter. +!!! error TS2680: A constructor cannot have a 'this' parameter. } } function notFirst(a: number, this: C): number { return this.n; } ~~~~~~~ -!!! error TS2673: 'this' parameter must be the first parameter. +!!! error TS2679: 'this' parameter must be the first parameter. ~ !!! error TS2339: Property 'n' does not exist on type 'void'. From 796613ce09dd25bdac8a3189f45f85210979126c Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 10 Mar 2016 06:51:57 -0800 Subject: [PATCH 115/274] Better error message + fix assignment analysis of 'switch' statement --- src/compiler/checker.ts | 29 +++++++++++++++++++--------- src/compiler/diagnosticMessages.json | 4 ++++ 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 117c66d3625..7eceab0956f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7222,6 +7222,7 @@ namespace ts { case SyntaxKind.ReturnStatement: case SyntaxKind.WithStatement: case SyntaxKind.SwitchStatement: + case SyntaxKind.CaseBlock: case SyntaxKind.CaseClause: case SyntaxKind.DefaultClause: case SyntaxKind.LabeledStatement: @@ -7683,6 +7684,7 @@ namespace ts { case SyntaxKind.ReturnStatement: case SyntaxKind.WithStatement: case SyntaxKind.SwitchStatement: + case SyntaxKind.CaseBlock: case SyntaxKind.CaseClause: case SyntaxKind.DefaultClause: case SyntaxKind.LabeledStatement: @@ -9541,6 +9543,15 @@ namespace ts { return true; } + function checkNonNullExpression(node: Expression | QualifiedName) { + const type = checkExpression(node); + if (strictNullChecks && getNullableKind(type)) { + error(node, Diagnostics.Object_is_possibly_null_or_undefined); + return getNonNullableType(type); + } + return type; + } + function checkPropertyAccessExpression(node: PropertyAccessExpression) { return checkPropertyAccessExpressionOrQualifiedName(node, node.expression, node.name); } @@ -9550,7 +9561,7 @@ namespace ts { } function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, right: Identifier) { - const type = checkExpression(left); + let type = checkNonNullExpression(left); if (isTypeAny(type)) { return type; } @@ -9661,7 +9672,7 @@ namespace ts { } // Obtain base constraint such that we can bail out if the constraint is an unknown type - const objectType = getApparentType(checkExpression(node.expression)); + const objectType = getApparentType(checkNonNullExpression(node.expression)); const indexType = node.argumentExpression ? checkExpression(node.argumentExpression) : unknownType; if (objectType === unknownType) { @@ -10676,7 +10687,7 @@ namespace ts { return resolveUntypedCall(node); } - const funcType = checkExpression(node.expression); + const funcType = checkNonNullExpression(node.expression); const apparentType = getApparentType(funcType); if (apparentType === unknownType) { @@ -10729,7 +10740,7 @@ namespace ts { } } - let expressionType = checkExpression(node.expression); + let expressionType = checkNonNullExpression(node.expression); // If expressionType's apparent type(section 3.8.1) is an object type with one or // more construct signatures, the expression is processed in the same manner as a @@ -10993,7 +11004,7 @@ namespace ts { return targetType; } - function checkNonNullExpression(node: NonNullExpression) { + function checkNonNullAssertion(node: NonNullExpression) { return getNonNullableType(checkExpression(node.expression)); } @@ -12178,7 +12189,7 @@ namespace ts { case SyntaxKind.AsExpression: return checkAssertion(node); case SyntaxKind.NonNullExpression: - return checkNonNullExpression(node); + return checkNonNullAssertion(node); case SyntaxKind.DeleteExpression: return checkDeleteExpression(node); case SyntaxKind.VoidExpression: @@ -14048,7 +14059,7 @@ namespace ts { } } - const rightType = checkExpression(node.expression); + const rightType = checkNonNullExpression(node.expression); // unknownType is returned i.e. if node.expression is identifier whose name cannot be resolved // in this case error about missing name is already reported - do not report extra one if (!isTypeAnyOrAllConstituentTypesHaveKind(rightType, TypeFlags.ObjectType | TypeFlags.TypeParameter)) { @@ -14068,7 +14079,7 @@ namespace ts { } function checkRightHandSideOfForOf(rhsExpression: Expression): Type { - const expressionType = getTypeOfExpression(rhsExpression); + const expressionType = checkNonNullExpression(rhsExpression); return checkIteratedTypeOrElementType(expressionType, rhsExpression, /*allowStringInput*/ true); } @@ -14339,7 +14350,7 @@ namespace ts { const signature = getSignatureFromDeclaration(func); const returnType = getReturnTypeOfSignature(signature); if (strictNullChecks || node.expression) { - const exprType = checkExpressionCached(node.expression); + const exprType = node.expression ? checkExpressionCached(node.expression) : undefinedType; if (func.asteriskToken) { // A generator does not need its return expressions checked against its return type. diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 01005bffe73..e47dc96fa22 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1715,6 +1715,10 @@ "category": "Error", "code": 2530 }, + "Object is possibly 'null' or 'undefined'.": { + "category": "Error", + "code": 2531 + }, "JSX element attributes type '{0}' may not be a union type.": { "category": "Error", "code": 2600 From dad05642d71408a864e80e0aad34fc43091e38ac Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 10 Mar 2016 11:13:30 -0800 Subject: [PATCH 116/274] Support 'this' in type guards --- src/compiler/checker.ts | 79 ++++++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 32 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7eceab0956f..f2a41ea5de8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7144,6 +7144,9 @@ namespace ts { const symbol = getResolvedSymbol(node); return symbol !== unknownSymbol ? "" + getSymbolId(symbol) : undefined; } + if (node.kind === SyntaxKind.ThisKeyword) { + return "0"; + } if (node.kind === SyntaxKind.PropertyAccessExpression) { const key = getAssignmentKey((node).expression); return key && key + "." + (node).name.text; @@ -7242,10 +7245,12 @@ namespace ts { } function isReferenceAssignedWithin(reference: Node, node: Node): boolean { - const key = getAssignmentKey(reference); - if (key) { - const links = getNodeLinks(node); - return (links.assignmentMap || (links.assignmentMap = getAssignmentMap(node)))[key]; + if (reference.kind !== SyntaxKind.ThisKeyword) { + const key = getAssignmentKey(reference); + if (key) { + const links = getNodeLinks(node); + return (links.assignmentMap || (links.assignmentMap = getAssignmentMap(node)))[key]; + } } return false; } @@ -7267,47 +7272,53 @@ namespace ts { node.kind === SyntaxKind.Identifier && getResolvedSymbol(node) === undefinedSymbol; } - function getLeftmostIdentifier(node: Node): Identifier { + function getLeftmostIdentifierOrThis(node: Node): Node { switch (node.kind) { case SyntaxKind.Identifier: - return node; + case SyntaxKind.ThisKeyword: + return node; case SyntaxKind.PropertyAccessExpression: - return getLeftmostIdentifier((node).expression); + return getLeftmostIdentifierOrThis((node).expression); } return undefined; } function isMatchingReference(source: Node, target: Node): boolean { if (source.kind === target.kind) { - if (source.kind === SyntaxKind.Identifier) { - return getResolvedSymbol(source) === getResolvedSymbol(target); - } - if (source.kind === SyntaxKind.PropertyAccessExpression) { - return (source).name.text === (target).name.text && - isMatchingReference((source).expression, (target).expression); + switch (source.kind) { + case SyntaxKind.Identifier: + return getResolvedSymbol(source) === getResolvedSymbol(target); + case SyntaxKind.ThisKeyword: + return true; + case SyntaxKind.PropertyAccessExpression: + return (source).name.text === (target).name.text && + isMatchingReference((source).expression, (target).expression); } } return false; } // Get the narrowed type of a given symbol at a given location - function getNarrowedTypeOfReference(type: Type, reference: IdentifierOrPropertyAccess) { + function getNarrowedTypeOfReference(type: Type, reference: Node) { if (!(type.flags & (TypeFlags.Any | TypeFlags.ObjectType | TypeFlags.Union | TypeFlags.TypeParameter))) { return type; } - const leftmostIdentifier = getLeftmostIdentifier(reference); - if (!leftmostIdentifier) { + const leftmostNode = getLeftmostIdentifierOrThis(reference); + if (!leftmostNode) { return type; } - const leftmostSymbol = getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(leftmostIdentifier)); - if (!leftmostSymbol) { - return type; + let top: Node; + if (leftmostNode.kind === SyntaxKind.Identifier) { + const leftmostSymbol = getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(leftmostNode)); + if (!leftmostSymbol) { + return type; + } + const declaration = leftmostSymbol.valueDeclaration; + if (!declaration || declaration.kind !== SyntaxKind.VariableDeclaration && declaration.kind !== SyntaxKind.Parameter && declaration.kind !== SyntaxKind.BindingElement) { + return type; + } + top = getDeclarationContainer(declaration); } - const declaration = leftmostSymbol.valueDeclaration; - if (!declaration || declaration.kind !== SyntaxKind.VariableDeclaration && declaration.kind !== SyntaxKind.Parameter && declaration.kind !== SyntaxKind.BindingElement) { - return type; - } - const top = getDeclarationContainer(declaration); const originalType = type; const nodeStack: { node: Node, child: Node }[] = []; let node: Node = reference; @@ -7322,11 +7333,12 @@ namespace ts { break; case SyntaxKind.SourceFile: case SyntaxKind.ModuleDeclaration: - // Stop at the first containing file or module declaration break loop; - } - if (node === top) { - break; + default: + if (node === top || isFunctionLikeKind(node.kind)) { + break loop; + } + break; } } @@ -7374,7 +7386,7 @@ namespace ts { return type; - function narrowTypeByTruthiness(type: Type, expr: Identifier, assumeTrue: boolean): Type { + function narrowTypeByTruthiness(type: Type, expr: Expression, assumeTrue: boolean): Type { return strictNullChecks && assumeTrue && isMatchingReference(expr, reference) ? getNonNullableType(type) : type; } @@ -7551,7 +7563,8 @@ namespace ts { } } - if (isTypeAssignableTo(narrowedTypeCandidate, originalType)) { + const targetType = originalType.flags & TypeFlags.TypeParameter ? getApparentType(originalType) : originalType; + if (isTypeAssignableTo(narrowedTypeCandidate, targetType)) { // Narrow to the target type if it's assignable to the current type return narrowedTypeCandidate; } @@ -7592,8 +7605,9 @@ namespace ts { function narrowType(type: Type, expr: Expression, assumeTrue: boolean): Type { switch (expr.kind) { case SyntaxKind.Identifier: + case SyntaxKind.ThisKeyword: case SyntaxKind.PropertyAccessExpression: - return narrowTypeByTruthiness(type, expr, assumeTrue); + return narrowTypeByTruthiness(type, expr, assumeTrue); case SyntaxKind.CallExpression: return narrowTypeByTypePredicate(type, expr, assumeTrue); case SyntaxKind.ParenthesizedExpression: @@ -8007,7 +8021,8 @@ namespace ts { if (isClassLike(container.parent)) { const symbol = getSymbolOfNode(container.parent); - return container.flags & NodeFlags.Static ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol)).thisType; + const type = container.flags & NodeFlags.Static ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol)).thisType; + return getNarrowedTypeOfReference(type, node); } if (isInJavaScriptFile(node)) { From 6772c3451945dea5e4fdbad60ea991d82e49fffb Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 10 Mar 2016 11:14:40 -0800 Subject: [PATCH 117/274] Accepting new baselines --- ...ationCollidingNamesInAugmentation1.symbols | 57 --------- ...ntationCollidingNamesInAugmentation1.types | 69 ----------- .../reference/typeGuardInClass.errors.txt | 30 +++++ .../reference/typeGuardInClass.symbols | 29 ----- .../reference/typeGuardInClass.types | 34 ------ .../reference/typeGuardsDefeat.errors.txt | 52 ++++++++ .../reference/typeGuardsDefeat.symbols | 82 ------------- .../reference/typeGuardsDefeat.types | 105 ---------------- ...typeGuardsInFunctionAndModuleBlock.symbols | 16 +-- .../typeGuardsInFunctionAndModuleBlock.types | 36 +++--- .../reference/typeGuardsInProperties.types | 16 +-- .../typeGuardsOnClassProperty.errors.txt | 34 ------ .../typeGuardsOnClassProperty.symbols | 86 ++++++++++++++ .../reference/typeGuardsOnClassProperty.types | 112 ++++++++++++++++++ 14 files changed, 314 insertions(+), 444 deletions(-) delete mode 100644 tests/baselines/reference/moduleAugmentationCollidingNamesInAugmentation1.symbols delete mode 100644 tests/baselines/reference/moduleAugmentationCollidingNamesInAugmentation1.types create mode 100644 tests/baselines/reference/typeGuardInClass.errors.txt delete mode 100644 tests/baselines/reference/typeGuardInClass.symbols delete mode 100644 tests/baselines/reference/typeGuardInClass.types create mode 100644 tests/baselines/reference/typeGuardsDefeat.errors.txt delete mode 100644 tests/baselines/reference/typeGuardsDefeat.symbols delete mode 100644 tests/baselines/reference/typeGuardsDefeat.types delete mode 100644 tests/baselines/reference/typeGuardsOnClassProperty.errors.txt create mode 100644 tests/baselines/reference/typeGuardsOnClassProperty.symbols create mode 100644 tests/baselines/reference/typeGuardsOnClassProperty.types diff --git a/tests/baselines/reference/moduleAugmentationCollidingNamesInAugmentation1.symbols b/tests/baselines/reference/moduleAugmentationCollidingNamesInAugmentation1.symbols deleted file mode 100644 index ec933695900..00000000000 --- a/tests/baselines/reference/moduleAugmentationCollidingNamesInAugmentation1.symbols +++ /dev/null @@ -1,57 +0,0 @@ -=== tests/cases/compiler/map1.ts === - -import { Observable } from "./observable" ->Observable : Symbol(Observable, Decl(map1.ts, 1, 8)) - -(Observable.prototype).map = function() { } ->Observable.prototype : Symbol(Observable.prototype) ->Observable : Symbol(Observable, Decl(map1.ts, 1, 8)) ->prototype : Symbol(Observable.prototype) - -declare module "./observable" { - interface I {x0} ->I : Symbol(I, Decl(map1.ts, 5, 31), Decl(map2.ts, 4, 31)) ->x0 : Symbol(x0, Decl(map1.ts, 6, 17)) -} - -=== tests/cases/compiler/map2.ts === -import { Observable } from "./observable" ->Observable : Symbol(Observable, Decl(map2.ts, 0, 8)) - -(Observable.prototype).map = function() { } ->Observable.prototype : Symbol(Observable.prototype) ->Observable : Symbol(Observable, Decl(map2.ts, 0, 8)) ->prototype : Symbol(Observable.prototype) - -declare module "./observable" { - interface I {x1} ->I : Symbol(I, Decl(map1.ts, 5, 31), Decl(map2.ts, 4, 31)) ->x1 : Symbol(x1, Decl(map2.ts, 5, 17)) -} - - -=== tests/cases/compiler/observable.ts === -export declare class Observable { ->Observable : Symbol(Observable, Decl(observable.ts, 0, 0)) ->T : Symbol(T, Decl(observable.ts, 0, 32)) - - filter(pred: (e:T) => boolean): Observable; ->filter : Symbol(filter, Decl(observable.ts, 0, 36)) ->pred : Symbol(pred, Decl(observable.ts, 1, 11)) ->e : Symbol(e, Decl(observable.ts, 1, 18)) ->T : Symbol(T, Decl(observable.ts, 0, 32)) ->Observable : Symbol(Observable, Decl(observable.ts, 0, 0)) ->T : Symbol(T, Decl(observable.ts, 0, 32)) -} - -=== tests/cases/compiler/main.ts === -import { Observable } from "./observable" ->Observable : Symbol(Observable, Decl(main.ts, 0, 8)) - -import "./map1"; -import "./map2"; - -let x: Observable; ->x : Symbol(x, Decl(main.ts, 4, 3)) ->Observable : Symbol(Observable, Decl(main.ts, 0, 8)) - diff --git a/tests/baselines/reference/moduleAugmentationCollidingNamesInAugmentation1.types b/tests/baselines/reference/moduleAugmentationCollidingNamesInAugmentation1.types deleted file mode 100644 index e87560c6a3d..00000000000 --- a/tests/baselines/reference/moduleAugmentationCollidingNamesInAugmentation1.types +++ /dev/null @@ -1,69 +0,0 @@ -=== tests/cases/compiler/map1.ts === - -import { Observable } from "./observable" ->Observable : typeof Observable - -(Observable.prototype).map = function() { } ->(Observable.prototype).map = function() { } : () => void ->(Observable.prototype).map : any ->(Observable.prototype) : any ->Observable.prototype : any ->Observable.prototype : Observable ->Observable : typeof Observable ->prototype : Observable ->map : any ->function() { } : () => void - -declare module "./observable" { - interface I {x0} ->I : I ->x0 : any -} - -=== tests/cases/compiler/map2.ts === -import { Observable } from "./observable" ->Observable : typeof Observable - -(Observable.prototype).map = function() { } ->(Observable.prototype).map = function() { } : () => void ->(Observable.prototype).map : any ->(Observable.prototype) : any ->Observable.prototype : any ->Observable.prototype : Observable ->Observable : typeof Observable ->prototype : Observable ->map : any ->function() { } : () => void - -declare module "./observable" { - interface I {x1} ->I : I ->x1 : any -} - - -=== tests/cases/compiler/observable.ts === -export declare class Observable { ->Observable : Observable ->T : T - - filter(pred: (e:T) => boolean): Observable; ->filter : (pred: (e: T) => boolean) => Observable ->pred : (e: T) => boolean ->e : T ->T : T ->Observable : Observable ->T : T -} - -=== tests/cases/compiler/main.ts === -import { Observable } from "./observable" ->Observable : typeof Observable - -import "./map1"; -import "./map2"; - -let x: Observable; ->x : Observable ->Observable : Observable - diff --git a/tests/baselines/reference/typeGuardInClass.errors.txt b/tests/baselines/reference/typeGuardInClass.errors.txt new file mode 100644 index 00000000000..aa86067576f --- /dev/null +++ b/tests/baselines/reference/typeGuardInClass.errors.txt @@ -0,0 +1,30 @@ +tests/cases/conformance/expressions/typeGuards/typeGuardInClass.ts(6,17): error TS2322: Type 'string | number' is not assignable to type 'string'. + Type 'number' is not assignable to type 'string'. +tests/cases/conformance/expressions/typeGuards/typeGuardInClass.ts(13,17): error TS2322: Type 'string | number' is not assignable to type 'number'. + Type 'string' is not assignable to type 'number'. + + +==== tests/cases/conformance/expressions/typeGuards/typeGuardInClass.ts (2 errors) ==== + let x: string | number; + + if (typeof x === "string") { + let n = class { + constructor() { + let y: string = x; + ~ +!!! error TS2322: Type 'string | number' is not assignable to type 'string'. +!!! error TS2322: Type 'number' is not assignable to type 'string'. + } + } + } + else { + let m = class { + constructor() { + let y: number = x; + ~ +!!! error TS2322: Type 'string | number' is not assignable to type 'number'. +!!! error TS2322: Type 'string' is not assignable to type 'number'. + } + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/typeGuardInClass.symbols b/tests/baselines/reference/typeGuardInClass.symbols deleted file mode 100644 index cc0e745e4de..00000000000 --- a/tests/baselines/reference/typeGuardInClass.symbols +++ /dev/null @@ -1,29 +0,0 @@ -=== tests/cases/conformance/expressions/typeGuards/typeGuardInClass.ts === -let x: string | number; ->x : Symbol(x, Decl(typeGuardInClass.ts, 0, 3)) - -if (typeof x === "string") { ->x : Symbol(x, Decl(typeGuardInClass.ts, 0, 3)) - - let n = class { ->n : Symbol(n, Decl(typeGuardInClass.ts, 3, 7)) - - constructor() { - let y: string = x; ->y : Symbol(y, Decl(typeGuardInClass.ts, 5, 15)) ->x : Symbol(x, Decl(typeGuardInClass.ts, 0, 3)) - } - } -} -else { - let m = class { ->m : Symbol(m, Decl(typeGuardInClass.ts, 10, 7)) - - constructor() { - let y: number = x; ->y : Symbol(y, Decl(typeGuardInClass.ts, 12, 15)) ->x : Symbol(x, Decl(typeGuardInClass.ts, 0, 3)) - } - } -} - diff --git a/tests/baselines/reference/typeGuardInClass.types b/tests/baselines/reference/typeGuardInClass.types deleted file mode 100644 index 93fe9f28c5e..00000000000 --- a/tests/baselines/reference/typeGuardInClass.types +++ /dev/null @@ -1,34 +0,0 @@ -=== tests/cases/conformance/expressions/typeGuards/typeGuardInClass.ts === -let x: string | number; ->x : string | number - -if (typeof x === "string") { ->typeof x === "string" : boolean ->typeof x : string ->x : string | number ->"string" : string - - let n = class { ->n : typeof (Anonymous class) ->class { constructor() { let y: string = x; } } : typeof (Anonymous class) - - constructor() { - let y: string = x; ->y : string ->x : string - } - } -} -else { - let m = class { ->m : typeof (Anonymous class) ->class { constructor() { let y: number = x; } } : typeof (Anonymous class) - - constructor() { - let y: number = x; ->y : number ->x : number - } - } -} - diff --git a/tests/baselines/reference/typeGuardsDefeat.errors.txt b/tests/baselines/reference/typeGuardsDefeat.errors.txt new file mode 100644 index 00000000000..d4006711d45 --- /dev/null +++ b/tests/baselines/reference/typeGuardsDefeat.errors.txt @@ -0,0 +1,52 @@ +tests/cases/conformance/expressions/typeGuards/typeGuardsDefeat.ts(21,20): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. +tests/cases/conformance/expressions/typeGuards/typeGuardsDefeat.ts(21,24): error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. +tests/cases/conformance/expressions/typeGuards/typeGuardsDefeat.ts(32,23): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. +tests/cases/conformance/expressions/typeGuards/typeGuardsDefeat.ts(32,27): error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. + + +==== tests/cases/conformance/expressions/typeGuards/typeGuardsDefeat.ts (4 errors) ==== + // Also note that it is possible to defeat a type guard by calling a function that changes the + // type of the guarded variable. + function foo(x: number | string) { + function f() { + x = 10; + } + if (typeof x === "string") { + f(); + return x.length; // string + } + else { + return x++; // number + } + } + function foo2(x: number | string) { + if (typeof x === "string") { + return x.length; // string + } + else { + var f = function () { + return x * x; + ~ +!!! error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. + ~ +!!! error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. + }; + } + x = "hello"; + f(); + } + function foo3(x: number | string) { + if (typeof x === "string") { + return x.length; // string + } + else { + var f = () => x * x; + ~ +!!! error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. + ~ +!!! error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. + } + x = "hello"; + f(); + } + \ No newline at end of file diff --git a/tests/baselines/reference/typeGuardsDefeat.symbols b/tests/baselines/reference/typeGuardsDefeat.symbols deleted file mode 100644 index 388b69b5789..00000000000 --- a/tests/baselines/reference/typeGuardsDefeat.symbols +++ /dev/null @@ -1,82 +0,0 @@ -=== tests/cases/conformance/expressions/typeGuards/typeGuardsDefeat.ts === -// Also note that it is possible to defeat a type guard by calling a function that changes the -// type of the guarded variable. -function foo(x: number | string) { ->foo : Symbol(foo, Decl(typeGuardsDefeat.ts, 0, 0)) ->x : Symbol(x, Decl(typeGuardsDefeat.ts, 2, 13)) - - function f() { ->f : Symbol(f, Decl(typeGuardsDefeat.ts, 2, 34)) - - x = 10; ->x : Symbol(x, Decl(typeGuardsDefeat.ts, 2, 13)) - } - if (typeof x === "string") { ->x : Symbol(x, Decl(typeGuardsDefeat.ts, 2, 13)) - - f(); ->f : Symbol(f, Decl(typeGuardsDefeat.ts, 2, 34)) - - return x.length; // string ->x.length : Symbol(String.length, Decl(lib.d.ts, --, --)) ->x : Symbol(x, Decl(typeGuardsDefeat.ts, 2, 13)) ->length : Symbol(String.length, Decl(lib.d.ts, --, --)) - } - else { - return x++; // number ->x : Symbol(x, Decl(typeGuardsDefeat.ts, 2, 13)) - } -} -function foo2(x: number | string) { ->foo2 : Symbol(foo2, Decl(typeGuardsDefeat.ts, 13, 1)) ->x : Symbol(x, Decl(typeGuardsDefeat.ts, 14, 14)) - - if (typeof x === "string") { ->x : Symbol(x, Decl(typeGuardsDefeat.ts, 14, 14)) - - return x.length; // string ->x.length : Symbol(String.length, Decl(lib.d.ts, --, --)) ->x : Symbol(x, Decl(typeGuardsDefeat.ts, 14, 14)) ->length : Symbol(String.length, Decl(lib.d.ts, --, --)) - } - else { - var f = function () { ->f : Symbol(f, Decl(typeGuardsDefeat.ts, 19, 11)) - - return x * x; ->x : Symbol(x, Decl(typeGuardsDefeat.ts, 14, 14)) ->x : Symbol(x, Decl(typeGuardsDefeat.ts, 14, 14)) - - }; - } - x = "hello"; ->x : Symbol(x, Decl(typeGuardsDefeat.ts, 14, 14)) - - f(); ->f : Symbol(f, Decl(typeGuardsDefeat.ts, 19, 11)) -} -function foo3(x: number | string) { ->foo3 : Symbol(foo3, Decl(typeGuardsDefeat.ts, 25, 1)) ->x : Symbol(x, Decl(typeGuardsDefeat.ts, 26, 14)) - - if (typeof x === "string") { ->x : Symbol(x, Decl(typeGuardsDefeat.ts, 26, 14)) - - return x.length; // string ->x.length : Symbol(String.length, Decl(lib.d.ts, --, --)) ->x : Symbol(x, Decl(typeGuardsDefeat.ts, 26, 14)) ->length : Symbol(String.length, Decl(lib.d.ts, --, --)) - } - else { - var f = () => x * x; ->f : Symbol(f, Decl(typeGuardsDefeat.ts, 31, 11)) ->x : Symbol(x, Decl(typeGuardsDefeat.ts, 26, 14)) ->x : Symbol(x, Decl(typeGuardsDefeat.ts, 26, 14)) - } - x = "hello"; ->x : Symbol(x, Decl(typeGuardsDefeat.ts, 26, 14)) - - f(); ->f : Symbol(f, Decl(typeGuardsDefeat.ts, 31, 11)) -} - diff --git a/tests/baselines/reference/typeGuardsDefeat.types b/tests/baselines/reference/typeGuardsDefeat.types deleted file mode 100644 index cc655d3ce0f..00000000000 --- a/tests/baselines/reference/typeGuardsDefeat.types +++ /dev/null @@ -1,105 +0,0 @@ -=== tests/cases/conformance/expressions/typeGuards/typeGuardsDefeat.ts === -// Also note that it is possible to defeat a type guard by calling a function that changes the -// type of the guarded variable. -function foo(x: number | string) { ->foo : (x: number | string) => number ->x : number | string - - function f() { ->f : () => void - - x = 10; ->x = 10 : number ->x : number | string ->10 : number - } - if (typeof x === "string") { ->typeof x === "string" : boolean ->typeof x : string ->x : number | string ->"string" : string - - f(); ->f() : void ->f : () => void - - return x.length; // string ->x.length : number ->x : string ->length : number - } - else { - return x++; // number ->x++ : number ->x : number - } -} -function foo2(x: number | string) { ->foo2 : (x: number | string) => number ->x : number | string - - if (typeof x === "string") { ->typeof x === "string" : boolean ->typeof x : string ->x : number | string ->"string" : string - - return x.length; // string ->x.length : number ->x : string ->length : number - } - else { - var f = function () { ->f : () => number ->function () { return x * x; } : () => number - - return x * x; ->x * x : number ->x : number ->x : number - - }; - } - x = "hello"; ->x = "hello" : string ->x : number | string ->"hello" : string - - f(); ->f() : number ->f : () => number -} -function foo3(x: number | string) { ->foo3 : (x: number | string) => number ->x : number | string - - if (typeof x === "string") { ->typeof x === "string" : boolean ->typeof x : string ->x : number | string ->"string" : string - - return x.length; // string ->x.length : number ->x : string ->length : number - } - else { - var f = () => x * x; ->f : () => number ->() => x * x : () => number ->x * x : number ->x : number ->x : number - } - x = "hello"; ->x = "hello" : string ->x : number | string ->"hello" : string - - f(); ->f() : number ->f : () => number -} - diff --git a/tests/baselines/reference/typeGuardsInFunctionAndModuleBlock.symbols b/tests/baselines/reference/typeGuardsInFunctionAndModuleBlock.symbols index 34810f303db..bf21641624e 100644 --- a/tests/baselines/reference/typeGuardsInFunctionAndModuleBlock.symbols +++ b/tests/baselines/reference/typeGuardsInFunctionAndModuleBlock.symbols @@ -27,9 +27,9 @@ function foo(x: number | string | boolean) { >toString : Symbol(Object.toString, Decl(lib.d.ts, --, --)) : x.toString(); // number ->x.toString : Symbol(Number.toString, Decl(lib.d.ts, --, --)) +>x.toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >x : Symbol(x, Decl(typeGuardsInFunctionAndModuleBlock.ts, 2, 13)) ->toString : Symbol(Number.toString, Decl(lib.d.ts, --, --)) +>toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) } (); } @@ -60,9 +60,9 @@ function foo2(x: number | string | boolean) { >toString : Symbol(Object.toString, Decl(lib.d.ts, --, --)) : x.toString(); // number ->x.toString : Symbol(Number.toString, Decl(lib.d.ts, --, --)) +>x.toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >x : Symbol(x, Decl(typeGuardsInFunctionAndModuleBlock.ts, 12, 14)) ->toString : Symbol(Number.toString, Decl(lib.d.ts, --, --)) +>toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) } (x); // x here is narrowed to number | boolean >x : Symbol(x, Decl(typeGuardsInFunctionAndModuleBlock.ts, 12, 14)) @@ -91,9 +91,9 @@ function foo3(x: number | string | boolean) { >toString : Symbol(Object.toString, Decl(lib.d.ts, --, --)) : x.toString(); // number ->x.toString : Symbol(Number.toString, Decl(lib.d.ts, --, --)) +>x.toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >x : Symbol(x, Decl(typeGuardsInFunctionAndModuleBlock.ts, 22, 14)) ->toString : Symbol(Number.toString, Decl(lib.d.ts, --, --)) +>toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) })(); } @@ -123,9 +123,9 @@ function foo4(x: number | string | boolean) { >toString : Symbol(Object.toString, Decl(lib.d.ts, --, --)) : x.toString(); // number ->x.toString : Symbol(Number.toString, Decl(lib.d.ts, --, --)) +>x.toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) >x : Symbol(x, Decl(typeGuardsInFunctionAndModuleBlock.ts, 32, 14)) ->toString : Symbol(Number.toString, Decl(lib.d.ts, --, --)) +>toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) })(x); // x here is narrowed to number | boolean >x : Symbol(x, Decl(typeGuardsInFunctionAndModuleBlock.ts, 32, 14)) diff --git a/tests/baselines/reference/typeGuardsInFunctionAndModuleBlock.types b/tests/baselines/reference/typeGuardsInFunctionAndModuleBlock.types index f7d56ed17d1..67d1816cfc3 100644 --- a/tests/baselines/reference/typeGuardsInFunctionAndModuleBlock.types +++ b/tests/baselines/reference/typeGuardsInFunctionAndModuleBlock.types @@ -21,14 +21,14 @@ function foo(x: number | string | boolean) { >f : () => string var b = x; // number | boolean ->b : number | boolean ->x : number | boolean +>b : number | string | boolean +>x : number | string | boolean return typeof x === "boolean" >typeof x === "boolean" ? x.toString() // boolean : x.toString() : string >typeof x === "boolean" : boolean >typeof x : string ->x : number | boolean +>x : number | string | boolean >"boolean" : string ? x.toString() // boolean @@ -40,7 +40,7 @@ function foo(x: number | string | boolean) { : x.toString(); // number >x.toString() : string >x.toString : (radix?: number) => string ->x : number +>x : number | string >toString : (radix?: number) => string } (); @@ -66,14 +66,14 @@ function foo2(x: number | string | boolean) { >a : number | boolean var b = x; // new scope - number | boolean ->b : number | boolean ->x : number | boolean +>b : number | string | boolean +>x : number | string | boolean return typeof x === "boolean" >typeof x === "boolean" ? x.toString() // boolean : x.toString() : string >typeof x === "boolean" : boolean >typeof x : string ->x : number | boolean +>x : number | string | boolean >"boolean" : string ? x.toString() // boolean @@ -85,7 +85,7 @@ function foo2(x: number | string | boolean) { : x.toString(); // number >x.toString() : string >x.toString : (radix?: number) => string ->x : number +>x : number | string >toString : (radix?: number) => string } (x); // x here is narrowed to number | boolean @@ -111,14 +111,14 @@ function foo3(x: number | string | boolean) { >() => { var b = x; // new scope - number | boolean return typeof x === "boolean" ? x.toString() // boolean : x.toString(); // number } : () => string var b = x; // new scope - number | boolean ->b : number | boolean ->x : number | boolean +>b : number | string | boolean +>x : number | string | boolean return typeof x === "boolean" >typeof x === "boolean" ? x.toString() // boolean : x.toString() : string >typeof x === "boolean" : boolean >typeof x : string ->x : number | boolean +>x : number | string | boolean >"boolean" : string ? x.toString() // boolean @@ -130,7 +130,7 @@ function foo3(x: number | string | boolean) { : x.toString(); // number >x.toString() : string >x.toString : (radix?: number) => string ->x : number +>x : number | string >toString : (radix?: number) => string })(); @@ -156,14 +156,14 @@ function foo4(x: number | string | boolean) { >a : number | boolean var b = x; // new scope - number | boolean ->b : number | boolean ->x : number | boolean +>b : number | string | boolean +>x : number | string | boolean return typeof x === "boolean" >typeof x === "boolean" ? x.toString() // boolean : x.toString() : string >typeof x === "boolean" : boolean >typeof x : string ->x : number | boolean +>x : number | string | boolean >"boolean" : string ? x.toString() // boolean @@ -175,7 +175,7 @@ function foo4(x: number | string | boolean) { : x.toString(); // number >x.toString() : string >x.toString : (radix?: number) => string ->x : number +>x : number | string >toString : (radix?: number) => string })(x); // x here is narrowed to number | boolean @@ -200,8 +200,8 @@ function foo5(x: number | string | boolean) { >foo : () => void var z = x; // string ->z : string ->x : string +>z : number | string | boolean +>x : number | string | boolean } } } diff --git a/tests/baselines/reference/typeGuardsInProperties.types b/tests/baselines/reference/typeGuardsInProperties.types index d6c9602a450..ef4cfbb5b05 100644 --- a/tests/baselines/reference/typeGuardsInProperties.types +++ b/tests/baselines/reference/typeGuardsInProperties.types @@ -29,32 +29,32 @@ class C1 { >method : () => void strOrNum = typeof this.pp1 === "string" && this.pp1; // string | number ->strOrNum = typeof this.pp1 === "string" && this.pp1 : string | number +>strOrNum = typeof this.pp1 === "string" && this.pp1 : string >strOrNum : string | number ->typeof this.pp1 === "string" && this.pp1 : string | number +>typeof this.pp1 === "string" && this.pp1 : string >typeof this.pp1 === "string" : boolean >typeof this.pp1 : string >this.pp1 : string | number >this : this >pp1 : string | number >"string" : string ->this.pp1 : string | number +>this.pp1 : string >this : this ->pp1 : string | number +>pp1 : string strOrNum = typeof this.pp2 === "string" && this.pp2; // string | number ->strOrNum = typeof this.pp2 === "string" && this.pp2 : string | number +>strOrNum = typeof this.pp2 === "string" && this.pp2 : string >strOrNum : string | number ->typeof this.pp2 === "string" && this.pp2 : string | number +>typeof this.pp2 === "string" && this.pp2 : string >typeof this.pp2 === "string" : boolean >typeof this.pp2 : string >this.pp2 : string | number >this : this >pp2 : string | number >"string" : string ->this.pp2 : string | number +>this.pp2 : string >this : this ->pp2 : string | number +>pp2 : string strOrNum = typeof this.pp3 === "string" && this.pp3; // string | number >strOrNum = typeof this.pp3 === "string" && this.pp3 : string | number diff --git a/tests/baselines/reference/typeGuardsOnClassProperty.errors.txt b/tests/baselines/reference/typeGuardsOnClassProperty.errors.txt deleted file mode 100644 index 660962ec1a7..00000000000 --- a/tests/baselines/reference/typeGuardsOnClassProperty.errors.txt +++ /dev/null @@ -1,34 +0,0 @@ -tests/cases/conformance/expressions/typeGuards/typeGuardsOnClassProperty.ts(14,70): error TS2339: Property 'join' does not exist on type 'string | string[]'. - - -==== tests/cases/conformance/expressions/typeGuards/typeGuardsOnClassProperty.ts (1 errors) ==== - // Note that type guards affect types of variables and parameters only and - // have no effect on members of objects such as properties. - - // Note that the class's property must be copied to a local variable for - // the type guard to have an effect - class D { - data: string | string[]; - getData() { - var data = this.data; - return typeof data === "string" ? data : data.join(" "); - } - - getData1() { - return typeof this.data === "string" ? this.data : this.data.join(" "); - ~~~~ -!!! error TS2339: Property 'join' does not exist on type 'string | string[]'. - } - } - - var o: { - prop1: number|string; - prop2: boolean|string; - } = { - prop1: "string" , - prop2: true - } - - if (typeof o.prop1 === "string" && o.prop1.toLowerCase()) {} - var prop1 = o.prop1; - if (typeof prop1 === "string" && prop1.toLocaleLowerCase()) { } \ No newline at end of file diff --git a/tests/baselines/reference/typeGuardsOnClassProperty.symbols b/tests/baselines/reference/typeGuardsOnClassProperty.symbols new file mode 100644 index 00000000000..f82df71e46a --- /dev/null +++ b/tests/baselines/reference/typeGuardsOnClassProperty.symbols @@ -0,0 +1,86 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardsOnClassProperty.ts === +// Note that type guards affect types of variables and parameters only and +// have no effect on members of objects such as properties. + +// Note that the class's property must be copied to a local variable for +// the type guard to have an effect +class D { +>D : Symbol(D, Decl(typeGuardsOnClassProperty.ts, 0, 0)) + + data: string | string[]; +>data : Symbol(data, Decl(typeGuardsOnClassProperty.ts, 5, 9)) + + getData() { +>getData : Symbol(getData, Decl(typeGuardsOnClassProperty.ts, 6, 28)) + + var data = this.data; +>data : Symbol(data, Decl(typeGuardsOnClassProperty.ts, 8, 11)) +>this.data : Symbol(data, Decl(typeGuardsOnClassProperty.ts, 5, 9)) +>this : Symbol(D, Decl(typeGuardsOnClassProperty.ts, 0, 0)) +>data : Symbol(data, Decl(typeGuardsOnClassProperty.ts, 5, 9)) + + return typeof data === "string" ? data : data.join(" "); +>data : Symbol(data, Decl(typeGuardsOnClassProperty.ts, 8, 11)) +>data : Symbol(data, Decl(typeGuardsOnClassProperty.ts, 8, 11)) +>data.join : Symbol(Array.join, Decl(lib.d.ts, --, --)) +>data : Symbol(data, Decl(typeGuardsOnClassProperty.ts, 8, 11)) +>join : Symbol(Array.join, Decl(lib.d.ts, --, --)) + } + + getData1() { +>getData1 : Symbol(getData1, Decl(typeGuardsOnClassProperty.ts, 10, 5)) + + return typeof this.data === "string" ? this.data : this.data.join(" "); +>this.data : Symbol(data, Decl(typeGuardsOnClassProperty.ts, 5, 9)) +>this : Symbol(D, Decl(typeGuardsOnClassProperty.ts, 0, 0)) +>data : Symbol(data, Decl(typeGuardsOnClassProperty.ts, 5, 9)) +>this.data : Symbol(data, Decl(typeGuardsOnClassProperty.ts, 5, 9)) +>this : Symbol(D, Decl(typeGuardsOnClassProperty.ts, 0, 0)) +>data : Symbol(data, Decl(typeGuardsOnClassProperty.ts, 5, 9)) +>this.data.join : Symbol(Array.join, Decl(lib.d.ts, --, --)) +>this.data : Symbol(data, Decl(typeGuardsOnClassProperty.ts, 5, 9)) +>this : Symbol(D, Decl(typeGuardsOnClassProperty.ts, 0, 0)) +>data : Symbol(data, Decl(typeGuardsOnClassProperty.ts, 5, 9)) +>join : Symbol(Array.join, Decl(lib.d.ts, --, --)) + } +} + +var o: { +>o : Symbol(o, Decl(typeGuardsOnClassProperty.ts, 17, 3)) + + prop1: number|string; +>prop1 : Symbol(prop1, Decl(typeGuardsOnClassProperty.ts, 17, 8)) + + prop2: boolean|string; +>prop2 : Symbol(prop2, Decl(typeGuardsOnClassProperty.ts, 18, 25)) + +} = { + prop1: "string" , +>prop1 : Symbol(prop1, Decl(typeGuardsOnClassProperty.ts, 20, 5)) + + prop2: true +>prop2 : Symbol(prop2, Decl(typeGuardsOnClassProperty.ts, 21, 25)) + } + +if (typeof o.prop1 === "string" && o.prop1.toLowerCase()) {} +>o.prop1 : Symbol(prop1, Decl(typeGuardsOnClassProperty.ts, 17, 8)) +>o : Symbol(o, Decl(typeGuardsOnClassProperty.ts, 17, 3)) +>prop1 : Symbol(prop1, Decl(typeGuardsOnClassProperty.ts, 17, 8)) +>o.prop1.toLowerCase : Symbol(String.toLowerCase, Decl(lib.d.ts, --, --)) +>o.prop1 : Symbol(prop1, Decl(typeGuardsOnClassProperty.ts, 17, 8)) +>o : Symbol(o, Decl(typeGuardsOnClassProperty.ts, 17, 3)) +>prop1 : Symbol(prop1, Decl(typeGuardsOnClassProperty.ts, 17, 8)) +>toLowerCase : Symbol(String.toLowerCase, Decl(lib.d.ts, --, --)) + +var prop1 = o.prop1; +>prop1 : Symbol(prop1, Decl(typeGuardsOnClassProperty.ts, 26, 3)) +>o.prop1 : Symbol(prop1, Decl(typeGuardsOnClassProperty.ts, 17, 8)) +>o : Symbol(o, Decl(typeGuardsOnClassProperty.ts, 17, 3)) +>prop1 : Symbol(prop1, Decl(typeGuardsOnClassProperty.ts, 17, 8)) + +if (typeof prop1 === "string" && prop1.toLocaleLowerCase()) { } +>prop1 : Symbol(prop1, Decl(typeGuardsOnClassProperty.ts, 26, 3)) +>prop1.toLocaleLowerCase : Symbol(String.toLocaleLowerCase, Decl(lib.d.ts, --, --)) +>prop1 : Symbol(prop1, Decl(typeGuardsOnClassProperty.ts, 26, 3)) +>toLocaleLowerCase : Symbol(String.toLocaleLowerCase, Decl(lib.d.ts, --, --)) + diff --git a/tests/baselines/reference/typeGuardsOnClassProperty.types b/tests/baselines/reference/typeGuardsOnClassProperty.types new file mode 100644 index 00000000000..6d524ccf674 --- /dev/null +++ b/tests/baselines/reference/typeGuardsOnClassProperty.types @@ -0,0 +1,112 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardsOnClassProperty.ts === +// Note that type guards affect types of variables and parameters only and +// have no effect on members of objects such as properties. + +// Note that the class's property must be copied to a local variable for +// the type guard to have an effect +class D { +>D : D + + data: string | string[]; +>data : string | string[] + + getData() { +>getData : () => string + + var data = this.data; +>data : string | string[] +>this.data : string | string[] +>this : this +>data : string | string[] + + return typeof data === "string" ? data : data.join(" "); +>typeof data === "string" ? data : data.join(" ") : string +>typeof data === "string" : boolean +>typeof data : string +>data : string | string[] +>"string" : string +>data : string +>data.join(" ") : string +>data.join : (separator?: string) => string +>data : string[] +>join : (separator?: string) => string +>" " : string + } + + getData1() { +>getData1 : () => string + + return typeof this.data === "string" ? this.data : this.data.join(" "); +>typeof this.data === "string" ? this.data : this.data.join(" ") : string +>typeof this.data === "string" : boolean +>typeof this.data : string +>this.data : string | string[] +>this : this +>data : string | string[] +>"string" : string +>this.data : string +>this : this +>data : string +>this.data.join(" ") : string +>this.data.join : (separator?: string) => string +>this.data : string[] +>this : this +>data : string[] +>join : (separator?: string) => string +>" " : string + } +} + +var o: { +>o : { prop1: number | string; prop2: boolean | string; } + + prop1: number|string; +>prop1 : number | string + + prop2: boolean|string; +>prop2 : boolean | string + +} = { +>{ prop1: "string" , prop2: true } : { prop1: string; prop2: boolean; } + + prop1: "string" , +>prop1 : string +>"string" : string + + prop2: true +>prop2 : boolean +>true : boolean + } + +if (typeof o.prop1 === "string" && o.prop1.toLowerCase()) {} +>typeof o.prop1 === "string" && o.prop1.toLowerCase() : string +>typeof o.prop1 === "string" : boolean +>typeof o.prop1 : string +>o.prop1 : number | string +>o : { prop1: number | string; prop2: boolean | string; } +>prop1 : number | string +>"string" : string +>o.prop1.toLowerCase() : string +>o.prop1.toLowerCase : () => string +>o.prop1 : string +>o : { prop1: number | string; prop2: boolean | string; } +>prop1 : string +>toLowerCase : () => string + +var prop1 = o.prop1; +>prop1 : number | string +>o.prop1 : number | string +>o : { prop1: number | string; prop2: boolean | string; } +>prop1 : number | string + +if (typeof prop1 === "string" && prop1.toLocaleLowerCase()) { } +>typeof prop1 === "string" && prop1.toLocaleLowerCase() : string +>typeof prop1 === "string" : boolean +>typeof prop1 : string +>prop1 : number | string +>"string" : string +>prop1.toLocaleLowerCase() : string +>prop1.toLocaleLowerCase : () => string +>prop1 : string +>toLocaleLowerCase : () => string + From 9c58875f416177335932e1ff9292119955443aec Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 10 Mar 2016 11:27:20 -0800 Subject: [PATCH 118/274] Fix linting error --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f2a41ea5de8..52373640f57 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9576,7 +9576,7 @@ namespace ts { } function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, right: Identifier) { - let type = checkNonNullExpression(left); + const type = checkNonNullExpression(left); if (isTypeAny(type)) { return type; } From 4c641c4147a87c87c83eb4e47cccc1557f38e266 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 10 Mar 2016 13:09:11 -0800 Subject: [PATCH 119/274] Add 'undefined' to type of parameter with default value in signature --- src/compiler/checker.ts | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 52373640f57..3511305e168 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5428,8 +5428,8 @@ namespace ts { const sourceParams = source.parameters; const targetParams = target.parameters; for (let i = 0; i < checkCount; i++) { - const s = i < sourceMax ? getTypeOfSymbol(sourceParams[i]) : getRestTypeOfSignature(source); - const t = i < targetMax ? getTypeOfSymbol(targetParams[i]) : getRestTypeOfSignature(target); + const s = i < sourceMax ? getTypeOfParameter(sourceParams[i]) : getRestTypeOfSignature(source); + const t = i < targetMax ? getTypeOfParameter(targetParams[i]) : getRestTypeOfSignature(target); const related = compareTypes(s, t, /*reportErrors*/ false) || compareTypes(t, s, reportErrors); if (!related) { if (reportErrors) { @@ -6409,8 +6409,8 @@ namespace ts { let result = Ternary.True; const targetLen = target.parameters.length; for (let i = 0; i < targetLen; i++) { - const s = isRestParameterIndex(source, i) ? getRestTypeOfSignature(source) : getTypeOfSymbol(source.parameters[i]); - const t = isRestParameterIndex(target, i) ? getRestTypeOfSignature(target) : getTypeOfSymbol(target.parameters[i]); + const s = isRestParameterIndex(source, i) ? getRestTypeOfSignature(source) : getTypeOfParameter(source.parameters[i]); + const t = isRestParameterIndex(target, i) ? getRestTypeOfSignature(target) : getTypeOfParameter(target.parameters[i]); const related = compareTypes(s, t); if (!related) { return Ternary.False; @@ -6777,8 +6777,8 @@ namespace ts { count = sourceMax < targetMax ? sourceMax : targetMax; } for (let i = 0; i < count; i++) { - const s = i < sourceMax ? getTypeOfSymbol(source.parameters[i]) : getRestTypeOfSignature(source); - const t = i < targetMax ? getTypeOfSymbol(target.parameters[i]) : getRestTypeOfSignature(target); + const s = i < sourceMax ? getTypeOfParameter(source.parameters[i]) : getRestTypeOfSignature(source); + const t = i < targetMax ? getTypeOfParameter(target.parameters[i]) : getRestTypeOfSignature(target); callback(s, t); } } @@ -11023,10 +11023,21 @@ namespace ts { return getNonNullableType(checkExpression(node.expression)); } + function getTypeOfParameter(symbol: Symbol) { + const type = getTypeOfSymbol(symbol); + if (strictNullChecks) { + const declaration = symbol.valueDeclaration; + if (declaration && (declaration).initializer) { + return addNullableKind(type, TypeFlags.Undefined); + } + } + return type; + } + function getTypeAtPosition(signature: Signature, pos: number): Type { return signature.hasRestParameter ? - pos < signature.parameters.length - 1 ? getTypeOfSymbol(signature.parameters[pos]) : getRestTypeOfSignature(signature) : - pos < signature.parameters.length ? getTypeOfSymbol(signature.parameters[pos]) : anyType; + pos < signature.parameters.length - 1 ? getTypeOfParameter(signature.parameters[pos]) : getRestTypeOfSignature(signature) : + pos < signature.parameters.length ? getTypeOfParameter(signature.parameters[pos]) : anyType; } function assignContextualParameterTypes(signature: Signature, context: Signature, mapper: TypeMapper) { From f774ecf4ec1e86b83f251720467d8f4732bf244f Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 10 Mar 2016 14:30:42 -0800 Subject: [PATCH 120/274] Remove 'undefined' from type of binding element with non-undefined default value --- src/compiler/checker.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3511305e168..10e4d50d930 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2678,6 +2678,11 @@ namespace ts { type = createArrayType(elementType); } } + // In strict null checking mode, if a default value of a non-undefined type is specified, remove + // undefined from the final type. + if (strictNullChecks && declaration.initializer && !(getNullableKind(checkExpressionCached(declaration.initializer)) & TypeFlags.Undefined)) { + type = removeNullableKind(type, TypeFlags.Undefined); + } return type; } From 1032cc54089c48025e361f91303942b9b7a54122 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 11 Mar 2016 13:24:31 -0800 Subject: [PATCH 121/274] Rename --strictThis to --strictThisChecks Use the upcoming naming scheme for --strict.*Checks and --strictChecks flags. --- src/compiler/binder.ts | 2 +- src/compiler/checker.ts | 4 ++-- src/compiler/commandLineParser.ts | 2 +- src/compiler/types.ts | 2 +- tests/baselines/reference/thisTypeInFunctions.js | 3 ++- tests/cases/conformance/types/thisType/thisTypeInFunctions.ts | 4 ++-- .../conformance/types/thisType/thisTypeInFunctionsNegative.ts | 2 +- .../conformance/types/thisType/unionThisTypeInFunctions.ts | 2 +- tests/cases/fourslash/memberListOnExplicitThis.ts | 2 +- tests/cases/fourslash/quickInfoOnThis.ts | 4 ++-- 10 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 10183f9a63f..7ae21a6338e 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1307,7 +1307,7 @@ namespace ts { // as other properties in the object literal. So we use SymbolFlags.PropertyExcludes // so that it will conflict with any other object literal members with the same // name. - if (options.strictThis) { + if (options.strictThisChecks) { seenThisKeyword = true; } return bindPropertyOrMethodOrAccessor(node, SymbolFlags.Method | ((node).questionToken ? SymbolFlags.Optional : SymbolFlags.None), diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4a1299196f1..5017f0dcd2c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3520,7 +3520,7 @@ namespace ts { return isIndependentVariableLikeDeclaration(declaration); case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: - return compilerOptions.strictThis ? false : isIndependentFunctionLikeDeclaration(declaration); + return compilerOptions.strictThisChecks ? false : isIndependentFunctionLikeDeclaration(declaration); case SyntaxKind.Constructor: return isIndependentFunctionLikeDeclaration(declaration); } @@ -4234,7 +4234,7 @@ namespace ts { if (minArgumentCount < 0) { minArgumentCount = declaration.parameters.length - (hasThisParameter ? 1 : 0); } - if (!hasThisParameter && compilerOptions.strictThis) { + if (!hasThisParameter && compilerOptions.strictThisChecks) { if (declaration.kind === SyntaxKind.FunctionDeclaration || declaration.kind === SyntaxKind.CallSignature || declaration.kind == SyntaxKind.FunctionExpression || diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 01d18d3a755..f6e1d9b48d7 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -138,7 +138,7 @@ namespace ts { type: "boolean", }, { - name: "strictThis", + name: "strictThisChecks", type: "boolean", }, { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 4d12e0bce99..dfa1b54e428 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2407,7 +2407,7 @@ namespace ts { rootDir?: string; sourceMap?: boolean; sourceRoot?: string; - strictThis?: boolean; + strictThisChecks?: boolean; suppressExcessPropertyErrors?: boolean; suppressImplicitAnyIndexErrors?: boolean; target?: ScriptTarget; diff --git a/tests/baselines/reference/thisTypeInFunctions.js b/tests/baselines/reference/thisTypeInFunctions.js index 8d34f9bc2cf..e963dad60f7 100644 --- a/tests/baselines/reference/thisTypeInFunctions.js +++ b/tests/baselines/reference/thisTypeInFunctions.js @@ -206,7 +206,8 @@ declare var f: { }; let n: number = f.call(12); -function missingTypeIsImplicitAny(this, a: number) { return a; } +function missingTypeIsImplicitAny(this, a: number) { return a; } + //// [thisTypeInFunctions.js] var __extends = (this && this.__extends) || function (d, b) { diff --git a/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts index 8676d12c5ab..3a1de178eea 100644 --- a/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts +++ b/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts @@ -1,4 +1,4 @@ -// @strictThis: true +// @strictThisChecks: true // body checking class B { n: number; @@ -206,4 +206,4 @@ declare var f: { }; let n: number = f.call(12); -function missingTypeIsImplicitAny(this, a: number) { return a; } \ No newline at end of file +function missingTypeIsImplicitAny(this, a: number) { return a; } diff --git a/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts b/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts index 3afc5a5c69b..bec0b9ab434 100644 --- a/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts +++ b/tests/cases/conformance/types/thisType/thisTypeInFunctionsNegative.ts @@ -1,4 +1,4 @@ -// @strictThis: true +// @strictThisChecks: true class C { n: number; explicitThis(this: this, m: number): number { diff --git a/tests/cases/conformance/types/thisType/unionThisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/unionThisTypeInFunctions.ts index a140c3fba95..c0a55f138ce 100644 --- a/tests/cases/conformance/types/thisType/unionThisTypeInFunctions.ts +++ b/tests/cases/conformance/types/thisType/unionThisTypeInFunctions.ts @@ -1,4 +1,4 @@ -// @strictThis: true +// @strictThisChecks: true interface Real { method(n: number): void; data: string; diff --git a/tests/cases/fourslash/memberListOnExplicitThis.ts b/tests/cases/fourslash/memberListOnExplicitThis.ts index cf57717183c..207ec8796fa 100644 --- a/tests/cases/fourslash/memberListOnExplicitThis.ts +++ b/tests/cases/fourslash/memberListOnExplicitThis.ts @@ -1,4 +1,4 @@ -// @strictThis: true +// @strictThisChecks: true /// ////interface Restricted { diff --git a/tests/cases/fourslash/quickInfoOnThis.ts b/tests/cases/fourslash/quickInfoOnThis.ts index 57bbb6c5a3e..bfed13ea89c 100644 --- a/tests/cases/fourslash/quickInfoOnThis.ts +++ b/tests/cases/fourslash/quickInfoOnThis.ts @@ -1,4 +1,4 @@ -// @strictThis: true +// @strictThisChecks: true /// ////interface Restricted { //// n: number; @@ -93,4 +93,4 @@ verify.quickInfoIs('this: {\n n: number;\n}'); goTo.marker('16'); verify.quickInfoIs('this: ContextualInterface'); goTo.marker('17'); -verify.quickInfoIs('(parameter) this: void'); \ No newline at end of file +verify.quickInfoIs('(parameter) this: void'); From b1bef15a1e05587f7b6a3471003ad2b773453b1f Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 14 Mar 2016 15:11:27 -0700 Subject: [PATCH 122/274] Removing 'T?' type notation (use 'T | null | undefined' instead) --- src/compiler/checker.ts | 24 +----------------------- src/compiler/parser.ts | 23 ++++++----------------- src/compiler/types.ts | 9 +-------- 3 files changed, 8 insertions(+), 48 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 10e4d50d930..5360cb558f8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2414,7 +2414,6 @@ namespace ts { case SyntaxKind.UnionType: case SyntaxKind.IntersectionType: case SyntaxKind.ParenthesizedType: - case SyntaxKind.NullableType: return isDeclarationVisible(node.parent); // Default binding, import specifier and namespace import is visible @@ -4779,14 +4778,6 @@ namespace ts { return links.resolvedType; } - function getTypeFromNullableTypeNode(node: NullableTypeNode): Type { - const links = getNodeLinks(node); - if (!links.resolvedType) { - links.resolvedType = getNullableType(getTypeFromTypeNode(node.type)); - } - return links.resolvedType; - } - interface TypeSet extends Array { containsAny?: boolean; containsUndefined?: boolean; @@ -5029,8 +5020,6 @@ namespace ts { return getTypeFromUnionTypeNode(node); case SyntaxKind.IntersectionType: return getTypeFromIntersectionTypeNode(node); - case SyntaxKind.NullableType: - return getTypeFromNullableTypeNode(node); case SyntaxKind.ParenthesizedType: case SyntaxKind.JSDocNullableType: case SyntaxKind.JSDocNonNullableType: @@ -6546,16 +6535,6 @@ namespace ts { return getNullableKind(type) === TypeFlags.Nullable; } - function getNullableType(type: Type): Type { - if (!strictNullChecks) { - return type; - } - if (!type.nullableType) { - type.nullableType = isNullableType(type) ? type : getUnionType([type, undefinedType, nullType]); - } - return type.nullableType; - } - function addNullableKind(type: Type, kind: TypeFlags): Type { if ((getNullableKind(type) & kind) !== kind) { const types = [type]; @@ -15792,8 +15771,7 @@ namespace ts { case SyntaxKind.IntersectionType: return checkUnionOrIntersectionType(node); case SyntaxKind.ParenthesizedType: - case SyntaxKind.NullableType: - return checkSourceElement((node).type); + return checkSourceElement((node).type); case SyntaxKind.FunctionDeclaration: return checkFunctionDeclaration(node); case SyntaxKind.Block: diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 0ff1dafc78b..a08c5755a3f 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -127,8 +127,7 @@ namespace ts { case SyntaxKind.IntersectionType: return visitNodes(cbNodes, (node).types); case SyntaxKind.ParenthesizedType: - case SyntaxKind.NullableType: - return visitNode(cbNode, (node).type); + return visitNode(cbNode, (node).type); case SyntaxKind.ObjectBindingPattern: case SyntaxKind.ArrayBindingPattern: return visitNodes(cbNodes, (node).elements); @@ -2426,21 +2425,11 @@ namespace ts { function parseArrayTypeOrHigher(): TypeNode { let type = parseNonArrayType(); - while (!scanner.hasPrecedingLineBreak()) { - if (parseOptional(SyntaxKind.OpenBracketToken)) { - parseExpected(SyntaxKind.CloseBracketToken); - const node = createNode(SyntaxKind.ArrayType, type.pos); - node.elementType = type; - type = finishNode(node); - } - else if (parseOptional(SyntaxKind.QuestionToken)) { - const node = createNode(SyntaxKind.NullableType, type.pos); - node.type = type; - type = finishNode(node); - } - else { - break; - } + while (!scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.OpenBracketToken)) { + parseExpected(SyntaxKind.CloseBracketToken); + const node = createNode(SyntaxKind.ArrayType, type.pos); + node.elementType = type; + type = finishNode(node); } return type; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 12ff2673564..3c7a16da59f 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -210,7 +210,6 @@ namespace ts { ParenthesizedType, ThisType, StringLiteralType, - NullableType, // Binding patterns ObjectBindingPattern, ArrayBindingPattern, @@ -357,7 +356,7 @@ namespace ts { FirstFutureReservedWord = ImplementsKeyword, LastFutureReservedWord = YieldKeyword, FirstTypeNode = TypePredicate, - LastTypeNode = NullableType, + LastTypeNode = StringLiteralType, FirstPunctuation = OpenBraceToken, LastPunctuation = CaretEqualsToken, FirstToken = Unknown, @@ -785,11 +784,6 @@ namespace ts { _stringLiteralTypeBrand: any; } - // @kind(SyntaxKind.NullableType) - export interface NullableTypeNode extends TypeNode { - type: TypeNode; - } - // @kind(SyntaxKind.StringLiteral) export interface StringLiteral extends LiteralExpression { _stringLiteralBrand: any; @@ -2152,7 +2146,6 @@ namespace ts { /* @internal */ id: number; // Unique ID symbol?: Symbol; // Symbol associated with type (if any) pattern?: DestructuringPattern; // Destructuring pattern represented by type (if any) - nullableType?: Type; // Cached nullable form of this type } /* @internal */ From 09ad9c524334fd9dd9c57dd9f15a33dc1bac77b8 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 14 Mar 2016 16:29:12 -0700 Subject: [PATCH 123/274] Remove 'T?' notation from type-to-string conversion --- src/compiler/checker.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5360cb558f8..4aeb3c50c92 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1885,10 +1885,6 @@ namespace ts { else if (type.flags & TypeFlags.Tuple) { writeTupleType(type); } - else if (isNullableType(type) && (type).types.length > 2) { - writeType(getNonNullableType(type), TypeFormatFlags.InElementType); - writePunctuation(writer, SyntaxKind.QuestionToken); - } else if (type.flags & TypeFlags.UnionOrIntersection) { writeUnionOrIntersectionType(type, flags); } @@ -6531,10 +6527,6 @@ namespace ts { getUnionType([nullType, undefinedType]) : nullType : undefinedType; } - function isNullableType(type: Type) { - return getNullableKind(type) === TypeFlags.Nullable; - } - function addNullableKind(type: Type, kind: TypeFlags): Type { if ((getNullableKind(type) & kind) !== kind) { const types = [type]; From 200f162bf64c8861781dadbc2b40873255685add Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Fri, 18 Mar 2016 11:27:21 -0700 Subject: [PATCH 124/274] rename LanguageService.getSourceFile to LanguageService.getNonBoundSourceFile and mark it as internal --- src/harness/fourslash.ts | 2 +- src/harness/harnessLanguageService.ts | 2 +- src/server/client.ts | 2 +- src/server/editorServices.ts | 2 +- src/services/services.ts | 6 +++--- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index ba7a5f20dae..2fba2d13299 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1414,7 +1414,7 @@ namespace FourSlash { return; } - const incrementalSourceFile = this.languageService.getSourceFile(this.activeFile.fileName); + const incrementalSourceFile = this.languageService.getNonBoundSourceFile(this.activeFile.fileName); Utils.assertInvariants(incrementalSourceFile, /*parent:*/ undefined); const incrementalSyntaxDiagnostics = incrementalSourceFile.parseDiagnostics; diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index 2a6ed85f9cd..12bb6a470e4 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -423,7 +423,7 @@ namespace Harness.LanguageService { getProgram(): ts.Program { throw new Error("Program can not be marshaled across the shim layer."); } - getSourceFile(fileName: string): ts.SourceFile { + getNonBoundSourceFile(fileName: string): ts.SourceFile { throw new Error("SourceFile can not be marshaled across the shim layer."); } dispose(): void { this.shim.dispose({}); } diff --git a/src/server/client.ts b/src/server/client.ts index 8731c52cc72..957d36e4a3a 100644 --- a/src/server/client.ts +++ b/src/server/client.ts @@ -613,7 +613,7 @@ namespace ts.server { throw new Error("SourceFile objects are not serializable through the server protocol."); } - getSourceFile(fileName: string): SourceFile { + getNonBoundSourceFile(fileName: string): SourceFile { throw new Error("SourceFile objects are not serializable through the server protocol."); } diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 42a2bded6a5..4a299ef6fd4 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1330,7 +1330,7 @@ namespace ts.server { } isExternalModule(filename: string): boolean { - const sourceFile = this.languageService.getSourceFile(filename); + const sourceFile = this.languageService.getNonBoundSourceFile(filename); return ts.isExternalModule(sourceFile); } diff --git a/src/services/services.ts b/src/services/services.ts index 72255b55479..a634b2baf1a 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1112,7 +1112,7 @@ namespace ts { getProgram(): Program; - getSourceFile(fileName: string): SourceFile; + /* @internal */ getNonBoundSourceFile(fileName: string): SourceFile; dispose(): void; } @@ -6528,7 +6528,7 @@ namespace ts { } /// Syntactic features - function getSourceFile(fileName: string): SourceFile { + function getNonBoundSourceFile(fileName: string): SourceFile { return syntaxTreeCache.getCurrentSourceFile(fileName); } @@ -7616,7 +7616,7 @@ namespace ts { getFormattingEditsAfterKeystroke, getDocCommentTemplateAtPosition, getEmitOutput, - getSourceFile, + getNonBoundSourceFile, getProgram }; } From 3691261db45d18063ea2077bbb2d1de4fa59fd31 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Fri, 18 Mar 2016 22:26:52 -0700 Subject: [PATCH 125/274] partially revert #7583 --- src/compiler/checker.ts | 4 ++-- .../reference/mergeWithImportedNamespace.js | 20 +++++++++++++++++++ .../mergeWithImportedNamespace.symbols | 17 ++++++++++++++++ .../mergeWithImportedNamespace.types | 18 +++++++++++++++++ .../reference/mergeWithImportedType.js | 18 +++++++++++++++++ .../reference/mergeWithImportedType.symbols | 14 +++++++++++++ .../reference/mergeWithImportedType.types | 14 +++++++++++++ .../compiler/mergeWithImportedNamespace.ts | 10 ++++++++++ tests/cases/compiler/mergeWithImportedType.ts | 8 ++++++++ 9 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/mergeWithImportedNamespace.js create mode 100644 tests/baselines/reference/mergeWithImportedNamespace.symbols create mode 100644 tests/baselines/reference/mergeWithImportedNamespace.types create mode 100644 tests/baselines/reference/mergeWithImportedType.js create mode 100644 tests/baselines/reference/mergeWithImportedType.symbols create mode 100644 tests/baselines/reference/mergeWithImportedType.types create mode 100644 tests/cases/compiler/mergeWithImportedNamespace.ts create mode 100644 tests/cases/compiler/mergeWithImportedType.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 27b08397205..6adb488aea9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15085,8 +15085,8 @@ namespace ts { // in order to prevent collisions with declarations that were exported from the current module (they still contribute to local names). const excludedMeanings = (symbol.flags & (SymbolFlags.Value | SymbolFlags.ExportValue) ? SymbolFlags.Value : 0) | - (symbol.flags & (SymbolFlags.Type | SymbolFlags.ExportType) ? SymbolFlags.Type : 0) | - (symbol.flags & (SymbolFlags.Namespace | SymbolFlags.ExportNamespace) ? SymbolFlags.Namespace : 0); + (symbol.flags & SymbolFlags.Type ? SymbolFlags.Type : 0) | + (symbol.flags & SymbolFlags.Namespace ? SymbolFlags.Namespace : 0); if (target.flags & excludedMeanings) { const message = node.kind === SyntaxKind.ExportSpecifier ? Diagnostics.Export_declaration_conflicts_with_exported_declaration_of_0 : diff --git a/tests/baselines/reference/mergeWithImportedNamespace.js b/tests/baselines/reference/mergeWithImportedNamespace.js new file mode 100644 index 00000000000..60f6fedd3f2 --- /dev/null +++ b/tests/baselines/reference/mergeWithImportedNamespace.js @@ -0,0 +1,20 @@ +//// [tests/cases/compiler/mergeWithImportedNamespace.ts] //// + +//// [f1.ts] +export namespace N { export var x = 1; } + +//// [f2.ts] +import {N} from "./f1"; +// partial revert of https://github.com/Microsoft/TypeScript/pull/7583 to prevent breaking changes +export namespace N { + export interface I {x: any} +} + +//// [f1.js] +"use strict"; +var N; +(function (N) { + N.x = 1; +})(N = exports.N || (exports.N = {})); +//// [f2.js] +"use strict"; diff --git a/tests/baselines/reference/mergeWithImportedNamespace.symbols b/tests/baselines/reference/mergeWithImportedNamespace.symbols new file mode 100644 index 00000000000..58b0f0a811f --- /dev/null +++ b/tests/baselines/reference/mergeWithImportedNamespace.symbols @@ -0,0 +1,17 @@ +=== tests/cases/compiler/f1.ts === +export namespace N { export var x = 1; } +>N : Symbol(N, Decl(f1.ts, 0, 0)) +>x : Symbol(x, Decl(f1.ts, 0, 31)) + +=== tests/cases/compiler/f2.ts === +import {N} from "./f1"; +>N : Symbol(N, Decl(f2.ts, 0, 8), Decl(f2.ts, 0, 23)) + +// partial revert of https://github.com/Microsoft/TypeScript/pull/7583 to prevent breaking changes +export namespace N { +>N : Symbol(N, Decl(f2.ts, 0, 23)) + + export interface I {x: any} +>I : Symbol(I, Decl(f2.ts, 2, 20)) +>x : Symbol(I.x, Decl(f2.ts, 3, 24)) +} diff --git a/tests/baselines/reference/mergeWithImportedNamespace.types b/tests/baselines/reference/mergeWithImportedNamespace.types new file mode 100644 index 00000000000..d6c1df3b609 --- /dev/null +++ b/tests/baselines/reference/mergeWithImportedNamespace.types @@ -0,0 +1,18 @@ +=== tests/cases/compiler/f1.ts === +export namespace N { export var x = 1; } +>N : typeof N +>x : number +>1 : number + +=== tests/cases/compiler/f2.ts === +import {N} from "./f1"; +>N : typeof N + +// partial revert of https://github.com/Microsoft/TypeScript/pull/7583 to prevent breaking changes +export namespace N { +>N : any + + export interface I {x: any} +>I : I +>x : any +} diff --git a/tests/baselines/reference/mergeWithImportedType.js b/tests/baselines/reference/mergeWithImportedType.js new file mode 100644 index 00000000000..89fc353d395 --- /dev/null +++ b/tests/baselines/reference/mergeWithImportedType.js @@ -0,0 +1,18 @@ +//// [tests/cases/compiler/mergeWithImportedType.ts] //// + +//// [f1.ts] +export enum E {X} + +//// [f2.ts] +import {E} from "./f1"; +// partial revert of https://github.com/Microsoft/TypeScript/pull/7583 to prevent breaking changes +export type E = E; + +//// [f1.js] +"use strict"; +(function (E) { + E[E["X"] = 0] = "X"; +})(exports.E || (exports.E = {})); +var E = exports.E; +//// [f2.js] +"use strict"; diff --git a/tests/baselines/reference/mergeWithImportedType.symbols b/tests/baselines/reference/mergeWithImportedType.symbols new file mode 100644 index 00000000000..d14d76f91e7 --- /dev/null +++ b/tests/baselines/reference/mergeWithImportedType.symbols @@ -0,0 +1,14 @@ +=== tests/cases/compiler/f1.ts === +export enum E {X} +>E : Symbol(E, Decl(f1.ts, 0, 0)) +>X : Symbol(E.X, Decl(f1.ts, 0, 15)) + +=== tests/cases/compiler/f2.ts === +import {E} from "./f1"; +>E : Symbol(E, Decl(f2.ts, 0, 8), Decl(f2.ts, 0, 23)) + +// partial revert of https://github.com/Microsoft/TypeScript/pull/7583 to prevent breaking changes +export type E = E; +>E : Symbol(E, Decl(f2.ts, 0, 23)) +>E : Symbol(E, Decl(f2.ts, 0, 8), Decl(f2.ts, 0, 23)) + diff --git a/tests/baselines/reference/mergeWithImportedType.types b/tests/baselines/reference/mergeWithImportedType.types new file mode 100644 index 00000000000..583492444c5 --- /dev/null +++ b/tests/baselines/reference/mergeWithImportedType.types @@ -0,0 +1,14 @@ +=== tests/cases/compiler/f1.ts === +export enum E {X} +>E : E +>X : E + +=== tests/cases/compiler/f2.ts === +import {E} from "./f1"; +>E : typeof E + +// partial revert of https://github.com/Microsoft/TypeScript/pull/7583 to prevent breaking changes +export type E = E; +>E : E +>E : E + diff --git a/tests/cases/compiler/mergeWithImportedNamespace.ts b/tests/cases/compiler/mergeWithImportedNamespace.ts new file mode 100644 index 00000000000..79a94fd0ba4 --- /dev/null +++ b/tests/cases/compiler/mergeWithImportedNamespace.ts @@ -0,0 +1,10 @@ +// @module:commonjs +// @filename: f1.ts +export namespace N { export var x = 1; } + +// @filename: f2.ts +import {N} from "./f1"; +// partial revert of https://github.com/Microsoft/TypeScript/pull/7583 to prevent breaking changes +export namespace N { + export interface I {x: any} +} \ No newline at end of file diff --git a/tests/cases/compiler/mergeWithImportedType.ts b/tests/cases/compiler/mergeWithImportedType.ts new file mode 100644 index 00000000000..2310022012f --- /dev/null +++ b/tests/cases/compiler/mergeWithImportedType.ts @@ -0,0 +1,8 @@ +// @module:commonjs +// @filename: f1.ts +export enum E {X} + +// @filename: f2.ts +import {E} from "./f1"; +// partial revert of https://github.com/Microsoft/TypeScript/pull/7583 to prevent breaking changes +export type E = E; \ No newline at end of file From 497b4c341c8488bb65e2ab1f3cb9553049cb0d57 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Sat, 19 Mar 2016 20:59:32 -0700 Subject: [PATCH 126/274] revert changes in the signature of 'convertCompilerOptionsFromJson' --- src/compiler/commandLineParser.ts | 30 ++++++++++++------- .../convertCompilerOptionsFromJson.ts | 3 +- .../unittests/convertTypingOptionsFromJson.ts | 3 +- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 2f10a8103c4..59ebf01d47f 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -590,9 +590,9 @@ namespace ts { */ export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions: CompilerOptions = {}, configFileName?: string): ParsedCommandLine { const errors: Diagnostic[] = []; - const compilerOptions: CompilerOptions = convertCompilerOptionsFromJson(optionDeclarations, json["compilerOptions"], basePath, errors, configFileName); + const compilerOptions: CompilerOptions = convertCompilerOptionsFromJsonWorker(json["compilerOptions"], basePath, errors, configFileName); const options = extend(existingOptions, compilerOptions); - const typingOptions: TypingOptions = convertTypingOptionsFromJson(typingOptionDeclarations, json["typingOptions"], basePath, errors, configFileName); + const typingOptions: TypingOptions = convertTypingOptionsFromJsonWorker(json["typingOptions"], basePath, errors, configFileName); const fileNames = getFileNames(errors); @@ -666,28 +666,38 @@ namespace ts { } } - /* @internal */ - export function convertCompilerOptionsFromJson(optionsDeclarations: CommandLineOption[], jsonOptions: any, + export function convertCompilerOptionsFromJson(jsonOptions: any, basePath: string, configFileName?: string): { options: CompilerOptions, errors: Diagnostic[] } { + const errors: Diagnostic[] = []; + const options = convertCompilerOptionsFromJsonWorker(jsonOptions, basePath, errors, configFileName); + return { options, errors }; + } + + export function convertTypingOptionsFromJson(jsonOptions: any, basePath: string, configFileName?: string): { options: CompilerOptions, errors: Diagnostic[] } { + const errors: Diagnostic[] = []; + const options = convertTypingOptionsFromJsonWorker(jsonOptions, basePath, errors, configFileName); + return { options, errors }; + } + + function convertCompilerOptionsFromJsonWorker(jsonOptions: any, basePath: string, errors: Diagnostic[], configFileName?: string): CompilerOptions { const options: CompilerOptions = getBaseFileName(configFileName) === "jsconfig.json" ? { allowJs: true } : {}; - convertOptionsFromJson(optionDeclarations, jsonOptions, basePath, options, Diagnostics.Unknown_compiler_option_0, errors); + convertOptionsFromJson(optionDeclarations, jsonOptions, basePath, options, Diagnostics.Unknown_compiler_option_0, errors); return options; } - /* @internal */ - export function convertTypingOptionsFromJson(optionsDeclarations: CommandLineOption[], jsonOptions: any, + function convertTypingOptionsFromJsonWorker(jsonOptions: any, basePath: string, errors: Diagnostic[], configFileName?: string): TypingOptions { const options: TypingOptions = getBaseFileName(configFileName) === "jsconfig.json" ? { enableAutoDiscovery: true, include: [], exclude: [] } : { enableAutoDiscovery: false, include: [], exclude: [] }; - convertOptionsFromJson(typingOptionDeclarations, jsonOptions, basePath, options, Diagnostics.Unknown_typing_option_0, errors); + convertOptionsFromJson(typingOptionDeclarations, jsonOptions, basePath, options, Diagnostics.Unknown_typing_option_0, errors); return options; } - function convertOptionsFromJson(optionDeclarations: CommandLineOption[], jsonOptions: any, basePath: string, - defaultOptions: T, diagnosticMessage: DiagnosticMessage, errors: Diagnostic[]) { + function convertOptionsFromJson(optionDeclarations: CommandLineOption[], jsonOptions: any, basePath: string, + defaultOptions: CompilerOptions | TypingOptions, diagnosticMessage: DiagnosticMessage, errors: Diagnostic[]) { if (!jsonOptions) { return ; diff --git a/tests/cases/unittests/convertCompilerOptionsFromJson.ts b/tests/cases/unittests/convertCompilerOptionsFromJson.ts index 4edc3bdd200..7ac80be7892 100644 --- a/tests/cases/unittests/convertCompilerOptionsFromJson.ts +++ b/tests/cases/unittests/convertCompilerOptionsFromJson.ts @@ -4,8 +4,7 @@ namespace ts { describe('convertCompilerOptionsFromJson', () => { function assertCompilerOptions(json: any, configFileName: string, expectedResult: { compilerOptions: CompilerOptions, errors: Diagnostic[] }) { - const actualErrors: Diagnostic[] = []; - const actualCompilerOptions: CompilerOptions = convertCompilerOptionsFromJson(optionDeclarations, json["compilerOptions"], "/apath/", actualErrors, configFileName); + const { options: actualCompilerOptions, errors: actualErrors} = convertCompilerOptionsFromJson(json["compilerOptions"], "/apath/", configFileName); const parsedCompilerOptions = JSON.stringify(actualCompilerOptions); const expectedCompilerOptions = JSON.stringify(expectedResult.compilerOptions); diff --git a/tests/cases/unittests/convertTypingOptionsFromJson.ts b/tests/cases/unittests/convertTypingOptionsFromJson.ts index 92b450555a9..3cd15a17c61 100644 --- a/tests/cases/unittests/convertTypingOptionsFromJson.ts +++ b/tests/cases/unittests/convertTypingOptionsFromJson.ts @@ -4,8 +4,7 @@ namespace ts { describe('convertTypingOptionsFromJson', () => { function assertTypingOptions(json: any, configFileName: string, expectedResult: { typingOptions: TypingOptions, errors: Diagnostic[] }) { - const actualErrors: Diagnostic[] = []; - const actualTypingOptions = convertTypingOptionsFromJson(typingOptionDeclarations, json["typingOptions"], "/apath/", actualErrors, configFileName); + const { options: actualTypingOptions, errors: actualErrors } = convertTypingOptionsFromJson(json["typingOptions"], "/apath/", configFileName); const parsedTypingOptions = JSON.stringify(actualTypingOptions); const expectedTypingOptions = JSON.stringify(expectedResult.typingOptions); assert.equal(parsedTypingOptions, expectedTypingOptions); From 07185c1c4a96230a783aa8a578318c6498ab8c5d Mon Sep 17 00:00:00 2001 From: zhengbli Date: Mon, 21 Mar 2016 12:55:55 -0700 Subject: [PATCH 127/274] Routine update of dom-related lib.d.ts --- src/lib/dom.generated.d.ts | 2219 ++++++++++++++++++++++-------- src/lib/webworker.generated.d.ts | 62 +- 2 files changed, 1666 insertions(+), 615 deletions(-) diff --git a/src/lib/dom.generated.d.ts b/src/lib/dom.generated.d.ts index ec71fa78e8d..59cd2675e7a 100644 --- a/src/lib/dom.generated.d.ts +++ b/src/lib/dom.generated.d.ts @@ -12,11 +12,6 @@ interface AriaRequestEventInit extends EventInit { attributeValue?: string; } -interface ClipboardEventInit extends EventInit { - data?: string; - dataType?: string; -} - interface CommandEventInit extends EventInit { commandName?: string; detail?: string; @@ -30,6 +25,31 @@ interface ConfirmSiteSpecificExceptionsInformation extends ExceptionInformation arrayOfDomainStrings?: string[]; } +interface ConstrainBooleanParameters { + exact?: boolean; + ideal?: boolean; +} + +interface ConstrainDOMStringParameters { + exact?: string | string[]; + ideal?: string | string[]; +} + +interface ConstrainDoubleRange extends DoubleRange { + exact?: number; + ideal?: number; +} + +interface ConstrainLongRange extends LongRange { + exact?: number; + ideal?: number; +} + +interface ConstrainVideoFacingModeParameters { + exact?: string | string[]; + ideal?: string | string[]; +} + interface CustomEventInit extends EventInit { detail?: any; } @@ -40,17 +60,44 @@ interface DeviceAccelerationDict { z?: number; } +interface DeviceLightEventInit extends EventInit { + value?: number; +} + interface DeviceRotationRateDict { alpha?: number; beta?: number; gamma?: number; } +interface DoubleRange { + max?: number; + min?: number; +} + interface EventInit { bubbles?: boolean; cancelable?: boolean; } +interface EventModifierInit extends UIEventInit { + ctrlKey?: boolean; + shiftKey?: boolean; + altKey?: boolean; + metaKey?: boolean; + modifierAltGraph?: boolean; + modifierCapsLock?: boolean; + modifierFn?: boolean; + modifierFnLock?: boolean; + modifierHyper?: boolean; + modifierNumLock?: boolean; + modifierOS?: boolean; + modifierScrollLock?: boolean; + modifierSuper?: boolean; + modifierSymbol?: boolean; + modifierSymbolLock?: boolean; +} + interface ExceptionInformation { domain?: string; } @@ -64,17 +111,415 @@ interface HashChangeEventInit extends EventInit { oldURL?: string; } +interface IDBIndexParameters { + multiEntry?: boolean; + unique?: boolean; +} + +interface IDBObjectStoreParameters { + autoIncrement?: boolean; + keyPath?: IDBKeyPath; +} + interface KeyAlgorithm { name?: string; } -interface KeyboardEventInit extends SharedKeyboardAndMouseEventInit { +interface KeyboardEventInit extends EventModifierInit { key?: string; location?: number; repeat?: boolean; } -interface MouseEventInit extends SharedKeyboardAndMouseEventInit { +interface LongRange { + max?: number; + min?: number; +} + +interface MSAccountInfo { + rpDisplayName?: string; + userDisplayName?: string; + accountName?: string; + userId?: string; + accountImageUri?: string; +} + +interface MSAudioLocalClientEvent extends MSLocalClientEventBase { + networkSendQualityEventRatio?: number; + networkDelayEventRatio?: number; + cpuInsufficientEventRatio?: number; + deviceHalfDuplexAECEventRatio?: number; + deviceRenderNotFunctioningEventRatio?: number; + deviceCaptureNotFunctioningEventRatio?: number; + deviceGlitchesEventRatio?: number; + deviceLowSNREventRatio?: number; + deviceLowSpeechLevelEventRatio?: number; + deviceClippingEventRatio?: number; + deviceEchoEventRatio?: number; + deviceNearEndToEchoRatioEventRatio?: number; + deviceRenderZeroVolumeEventRatio?: number; + deviceRenderMuteEventRatio?: number; + deviceMultipleEndpointsEventCount?: number; + deviceHowlingEventCount?: number; +} + +interface MSAudioRecvPayload extends MSPayloadBase { + samplingRate?: number; + signal?: MSAudioRecvSignal; + packetReorderRatio?: number; + packetReorderDepthAvg?: number; + packetReorderDepthMax?: number; + burstLossLength1?: number; + burstLossLength2?: number; + burstLossLength3?: number; + burstLossLength4?: number; + burstLossLength5?: number; + burstLossLength6?: number; + burstLossLength7?: number; + burstLossLength8OrHigher?: number; + fecRecvDistance1?: number; + fecRecvDistance2?: number; + fecRecvDistance3?: number; + ratioConcealedSamplesAvg?: number; + ratioStretchedSamplesAvg?: number; + ratioCompressedSamplesAvg?: number; +} + +interface MSAudioRecvSignal { + initialSignalLevelRMS?: number; + recvSignalLevelCh1?: number; + recvNoiseLevelCh1?: number; + renderSignalLevel?: number; + renderNoiseLevel?: number; + renderLoopbackSignalLevel?: number; +} + +interface MSAudioSendPayload extends MSPayloadBase { + samplingRate?: number; + signal?: MSAudioSendSignal; + audioFECUsed?: boolean; + sendMutePercent?: number; +} + +interface MSAudioSendSignal { + noiseLevel?: number; + sendSignalLevelCh1?: number; + sendNoiseLevelCh1?: number; +} + +interface MSConnectivity { + iceType?: string; + iceWarningFlags?: MSIceWarningFlags; + relayAddress?: MSRelayAddress; +} + +interface MSCredentialFilter { + accept?: MSCredentialSpec[]; +} + +interface MSCredentialParameters { + type?: string; +} + +interface MSCredentialSpec { + type?: string; + id?: string; +} + +interface MSDelay { + roundTrip?: number; + roundTripMax?: number; +} + +interface MSDescription extends RTCStats { + connectivity?: MSConnectivity; + transport?: string; + networkconnectivity?: MSNetworkConnectivityInfo; + localAddr?: MSIPAddressInfo; + remoteAddr?: MSIPAddressInfo; + deviceDevName?: string; + reflexiveLocalIPAddr?: MSIPAddressInfo; +} + +interface MSFIDOCredentialParameters extends MSCredentialParameters { + algorithm?: string | Algorithm; + authenticators?: AAGUID[]; +} + +interface MSIPAddressInfo { + ipAddr?: string; + port?: number; + manufacturerMacAddrMask?: string; +} + +interface MSIceWarningFlags { + turnTcpTimedOut?: boolean; + turnUdpAllocateFailed?: boolean; + turnUdpSendFailed?: boolean; + turnTcpAllocateFailed?: boolean; + turnTcpSendFailed?: boolean; + udpLocalConnectivityFailed?: boolean; + udpNatConnectivityFailed?: boolean; + udpRelayConnectivityFailed?: boolean; + tcpNatConnectivityFailed?: boolean; + tcpRelayConnectivityFailed?: boolean; + connCheckMessageIntegrityFailed?: boolean; + allocationMessageIntegrityFailed?: boolean; + connCheckOtherError?: boolean; + turnAuthUnknownUsernameError?: boolean; + noRelayServersConfigured?: boolean; + multipleRelayServersAttempted?: boolean; + portRangeExhausted?: boolean; + alternateServerReceived?: boolean; + pseudoTLSFailure?: boolean; + turnTurnTcpConnectivityFailed?: boolean; + useCandidateChecksFailed?: boolean; + fipsAllocationFailure?: boolean; +} + +interface MSJitter { + interArrival?: number; + interArrivalMax?: number; + interArrivalSD?: number; +} + +interface MSLocalClientEventBase extends RTCStats { + networkReceiveQualityEventRatio?: number; + networkBandwidthLowEventRatio?: number; +} + +interface MSNetwork extends RTCStats { + jitter?: MSJitter; + delay?: MSDelay; + packetLoss?: MSPacketLoss; + utilization?: MSUtilization; +} + +interface MSNetworkConnectivityInfo { + vpn?: boolean; + linkspeed?: number; + networkConnectionDetails?: string; +} + +interface MSNetworkInterfaceType { + interfaceTypeEthernet?: boolean; + interfaceTypeWireless?: boolean; + interfaceTypePPP?: boolean; + interfaceTypeTunnel?: boolean; + interfaceTypeWWAN?: boolean; +} + +interface MSOutboundNetwork extends MSNetwork { + appliedBandwidthLimit?: number; +} + +interface MSPacketLoss { + lossRate?: number; + lossRateMax?: number; +} + +interface MSPayloadBase extends RTCStats { + payloadDescription?: string; +} + +interface MSRelayAddress { + relayAddress?: string; + port?: number; +} + +interface MSSignatureParameters { + userPrompt?: string; +} + +interface MSTransportDiagnosticsStats extends RTCStats { + baseAddress?: string; + localAddress?: string; + localSite?: string; + networkName?: string; + remoteAddress?: string; + remoteSite?: string; + localMR?: string; + remoteMR?: string; + iceWarningFlags?: MSIceWarningFlags; + portRangeMin?: number; + portRangeMax?: number; + localMRTCPPort?: number; + remoteMRTCPPort?: number; + stunVer?: number; + numConsentReqSent?: number; + numConsentReqReceived?: number; + numConsentRespSent?: number; + numConsentRespReceived?: number; + interfaces?: MSNetworkInterfaceType; + baseInterface?: MSNetworkInterfaceType; + protocol?: string; + localInterface?: MSNetworkInterfaceType; + localAddrType?: string; + remoteAddrType?: string; + iceRole?: string; + rtpRtcpMux?: boolean; + allocationTimeInMs?: number; + msRtcEngineVersion?: string; +} + +interface MSUtilization { + packets?: number; + bandwidthEstimation?: number; + bandwidthEstimationMin?: number; + bandwidthEstimationMax?: number; + bandwidthEstimationStdDev?: number; + bandwidthEstimationAvg?: number; +} + +interface MSVideoPayload extends MSPayloadBase { + resoluton?: string; + videoBitRateAvg?: number; + videoBitRateMax?: number; + videoFrameRateAvg?: number; + videoPacketLossRate?: number; + durationSeconds?: number; +} + +interface MSVideoRecvPayload extends MSVideoPayload { + videoFrameLossRate?: number; + recvCodecType?: string; + recvResolutionWidth?: number; + recvResolutionHeight?: number; + videoResolutions?: MSVideoResolutionDistribution; + recvFrameRateAverage?: number; + recvBitRateMaximum?: number; + recvBitRateAverage?: number; + recvVideoStreamsMax?: number; + recvVideoStreamsMin?: number; + recvVideoStreamsMode?: number; + videoPostFECPLR?: number; + lowBitRateCallPercent?: number; + lowFrameRateCallPercent?: number; + reorderBufferTotalPackets?: number; + recvReorderBufferReorderedPackets?: number; + recvReorderBufferPacketsDroppedDueToBufferExhaustion?: number; + recvReorderBufferMaxSuccessfullyOrderedExtent?: number; + recvReorderBufferMaxSuccessfullyOrderedLateTime?: number; + recvReorderBufferPacketsDroppedDueToTimeout?: number; + recvFpsHarmonicAverage?: number; + recvNumResSwitches?: number; +} + +interface MSVideoResolutionDistribution { + cifQuality?: number; + vgaQuality?: number; + h720Quality?: number; + h1080Quality?: number; + h1440Quality?: number; + h2160Quality?: number; +} + +interface MSVideoSendPayload extends MSVideoPayload { + sendFrameRateAverage?: number; + sendBitRateMaximum?: number; + sendBitRateAverage?: number; + sendVideoStreamsMax?: number; + sendResolutionWidth?: number; + sendResolutionHeight?: number; +} + +interface MediaEncryptedEventInit extends EventInit { + initDataType?: string; + initData?: ArrayBuffer; +} + +interface MediaKeyMessageEventInit extends EventInit { + messageType?: string; + message?: ArrayBuffer; +} + +interface MediaKeySystemConfiguration { + initDataTypes?: string[]; + audioCapabilities?: MediaKeySystemMediaCapability[]; + videoCapabilities?: MediaKeySystemMediaCapability[]; + distinctiveIdentifier?: string; + persistentState?: string; +} + +interface MediaKeySystemMediaCapability { + contentType?: string; + robustness?: string; +} + +interface MediaStreamConstraints { + video?: boolean | MediaTrackConstraints; + audio?: boolean | MediaTrackConstraints; +} + +interface MediaStreamErrorEventInit extends EventInit { + error?: MediaStreamError; +} + +interface MediaStreamTrackEventInit extends EventInit { + track?: MediaStreamTrack; +} + +interface MediaTrackCapabilities { + width?: number | LongRange; + height?: number | LongRange; + aspectRatio?: number | DoubleRange; + frameRate?: number | DoubleRange; + facingMode?: string; + volume?: number | DoubleRange; + sampleRate?: number | LongRange; + sampleSize?: number | LongRange; + echoCancellation?: boolean[]; + deviceId?: string; + groupId?: string; +} + +interface MediaTrackConstraintSet { + width?: number | ConstrainLongRange; + height?: number | ConstrainLongRange; + aspectRatio?: number | ConstrainDoubleRange; + frameRate?: number | ConstrainDoubleRange; + facingMode?: string | string[] | ConstrainDOMStringParameters; + volume?: number | ConstrainDoubleRange; + sampleRate?: number | ConstrainLongRange; + sampleSize?: number | ConstrainLongRange; + echoCancelation?: boolean | ConstrainBooleanParameters; + deviceId?: string | string[] | ConstrainDOMStringParameters; + groupId?: string | string[] | ConstrainDOMStringParameters; +} + +interface MediaTrackConstraints extends MediaTrackConstraintSet { + advanced?: MediaTrackConstraintSet[]; +} + +interface MediaTrackSettings { + width?: number; + height?: number; + aspectRatio?: number; + frameRate?: number; + facingMode?: string; + volume?: number; + sampleRate?: number; + sampleSize?: number; + echoCancellation?: boolean; + deviceId?: string; + groupId?: string; +} + +interface MediaTrackSupportedConstraints { + width?: boolean; + height?: boolean; + aspectRatio?: boolean; + frameRate?: boolean; + facingMode?: boolean; + volume?: boolean; + sampleRate?: boolean; + sampleSize?: boolean; + echoCancellation?: boolean; + deviceId?: boolean; + groupId?: boolean; +} + +interface MouseEventInit extends EventModifierInit { screenX?: number; screenY?: number; clientX?: number; @@ -107,6 +552,10 @@ interface ObjectURLOptions { oneTimeOnly?: boolean; } +interface PeriodicWaveConstraints { + disableNormalization?: boolean; +} + interface PointerEventInit extends MouseEventInit { pointerId?: number; width?: number; @@ -124,22 +573,266 @@ interface PositionOptions { maximumAge?: number; } -interface SharedKeyboardAndMouseEventInit extends UIEventInit { - ctrlKey?: boolean; - shiftKey?: boolean; - altKey?: boolean; - metaKey?: boolean; - keyModifierStateAltGraph?: boolean; - keyModifierStateCapsLock?: boolean; - keyModifierStateFn?: boolean; - keyModifierStateFnLock?: boolean; - keyModifierStateHyper?: boolean; - keyModifierStateNumLock?: boolean; - keyModifierStateOS?: boolean; - keyModifierStateScrollLock?: boolean; - keyModifierStateSuper?: boolean; - keyModifierStateSymbol?: boolean; - keyModifierStateSymbolLock?: boolean; +interface RTCDTMFToneChangeEventInit extends EventInit { + tone?: string; +} + +interface RTCDtlsFingerprint { + algorithm?: string; + value?: string; +} + +interface RTCDtlsParameters { + role?: string; + fingerprints?: RTCDtlsFingerprint[]; +} + +interface RTCIceCandidate { + foundation?: string; + priority?: number; + ip?: string; + protocol?: string; + port?: number; + type?: string; + tcpType?: string; + relatedAddress?: string; + relatedPort?: number; +} + +interface RTCIceCandidateAttributes extends RTCStats { + ipAddress?: string; + portNumber?: number; + transport?: string; + candidateType?: string; + priority?: number; + addressSourceUrl?: string; +} + +interface RTCIceCandidateComplete { +} + +interface RTCIceCandidatePair { + local?: RTCIceCandidate; + remote?: RTCIceCandidate; +} + +interface RTCIceCandidatePairStats extends RTCStats { + transportId?: string; + localCandidateId?: string; + remoteCandidateId?: string; + state?: string; + priority?: number; + nominated?: boolean; + writable?: boolean; + readable?: boolean; + bytesSent?: number; + bytesReceived?: number; + roundTripTime?: number; + availableOutgoingBitrate?: number; + availableIncomingBitrate?: number; +} + +interface RTCIceGatherOptions { + gatherPolicy?: string; + iceservers?: RTCIceServer[]; +} + +interface RTCIceParameters { + usernameFragment?: string; + password?: string; +} + +interface RTCIceServer { + urls?: any; + username?: string; + credential?: string; +} + +interface RTCInboundRTPStreamStats extends RTCRTPStreamStats { + packetsReceived?: number; + bytesReceived?: number; + packetsLost?: number; + jitter?: number; + fractionLost?: number; +} + +interface RTCMediaStreamTrackStats extends RTCStats { + trackIdentifier?: string; + remoteSource?: boolean; + ssrcIds?: string[]; + frameWidth?: number; + frameHeight?: number; + framesPerSecond?: number; + framesSent?: number; + framesReceived?: number; + framesDecoded?: number; + framesDropped?: number; + framesCorrupted?: number; + audioLevel?: number; + echoReturnLoss?: number; + echoReturnLossEnhancement?: number; +} + +interface RTCOutboundRTPStreamStats extends RTCRTPStreamStats { + packetsSent?: number; + bytesSent?: number; + targetBitrate?: number; + roundTripTime?: number; +} + +interface RTCRTPStreamStats extends RTCStats { + ssrc?: string; + associateStatsId?: string; + isRemote?: boolean; + mediaTrackId?: string; + transportId?: string; + codecId?: string; + firCount?: number; + pliCount?: number; + nackCount?: number; + sliCount?: number; +} + +interface RTCRtcpFeedback { + type?: string; + parameter?: string; +} + +interface RTCRtcpParameters { + ssrc?: number; + cname?: string; + reducedSize?: boolean; + mux?: boolean; +} + +interface RTCRtpCapabilities { + codecs?: RTCRtpCodecCapability[]; + headerExtensions?: RTCRtpHeaderExtension[]; + fecMechanisms?: string[]; +} + +interface RTCRtpCodecCapability { + name?: string; + kind?: string; + clockRate?: number; + preferredPayloadType?: number; + maxptime?: number; + numChannels?: number; + rtcpFeedback?: RTCRtcpFeedback[]; + parameters?: any; + options?: any; + maxTemporalLayers?: number; + maxSpatialLayers?: number; + svcMultiStreamSupport?: boolean; +} + +interface RTCRtpCodecParameters { + name?: string; + payloadType?: any; + clockRate?: number; + maxptime?: number; + numChannels?: number; + rtcpFeedback?: RTCRtcpFeedback[]; + parameters?: any; +} + +interface RTCRtpContributingSource { + timestamp?: number; + csrc?: number; + audioLevel?: number; +} + +interface RTCRtpEncodingParameters { + ssrc?: number; + codecPayloadType?: number; + fec?: RTCRtpFecParameters; + rtx?: RTCRtpRtxParameters; + priority?: number; + maxBitrate?: number; + minQuality?: number; + framerateBias?: number; + resolutionScale?: number; + framerateScale?: number; + active?: boolean; + encodingId?: string; + dependencyEncodingIds?: string[]; + ssrcRange?: RTCSsrcRange; +} + +interface RTCRtpFecParameters { + ssrc?: number; + mechanism?: string; +} + +interface RTCRtpHeaderExtension { + kind?: string; + uri?: string; + preferredId?: number; + preferredEncrypt?: boolean; +} + +interface RTCRtpHeaderExtensionParameters { + uri?: string; + id?: number; + encrypt?: boolean; +} + +interface RTCRtpParameters { + muxId?: string; + codecs?: RTCRtpCodecParameters[]; + headerExtensions?: RTCRtpHeaderExtensionParameters[]; + encodings?: RTCRtpEncodingParameters[]; + rtcp?: RTCRtcpParameters; +} + +interface RTCRtpRtxParameters { + ssrc?: number; +} + +interface RTCRtpUnhandled { + ssrc?: number; + payloadType?: number; + muxId?: string; +} + +interface RTCSrtpKeyParam { + keyMethod?: string; + keySalt?: string; + lifetime?: string; + mkiValue?: number; + mkiLength?: number; +} + +interface RTCSrtpSdesParameters { + tag?: number; + cryptoSuite?: string; + keyParams?: RTCSrtpKeyParam[]; + sessionParams?: string[]; +} + +interface RTCSsrcRange { + min?: number; + max?: number; +} + +interface RTCStats { + timestamp?: number; + type?: string; + id?: string; + msType?: string; +} + +interface RTCStatsReport { +} + +interface RTCTransportStats extends RTCStats { + bytesSent?: number; + bytesReceived?: number; + rtcpTransportStatsId?: string; + activeConnection?: boolean; + selectedCandidatePairId?: string; + localCertificateId?: string; + remoteCertificateId?: string; } interface StoreExceptionsInformation extends ExceptionInformation { @@ -276,6 +969,7 @@ declare var AriaRequestEvent: { interface Attr extends Node { name: string; ownerElement: Element; + prefix: string; specified: boolean; value: string; } @@ -290,6 +984,8 @@ interface AudioBuffer { length: number; numberOfChannels: number; sampleRate: number; + copyFromChannel(destination: Float32Array, channelNumber: number, startInChannel?: number): void; + copyToChannel(source: Float32Array, channelNumber: number, startInChannel?: number): void; getChannelData(channel: number): Float32Array; } @@ -300,14 +996,15 @@ declare var AudioBuffer: { interface AudioBufferSourceNode extends AudioNode { buffer: AudioBuffer; + detune: AudioParam; loop: boolean; loopEnd: number; loopStart: number; - onended: (ev: Event) => any; + onended: (ev: MediaStreamErrorEvent) => any; playbackRate: AudioParam; start(when?: number, offset?: number, duration?: number): void; stop(when?: number): void; - addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "ended", listener: (ev: MediaStreamErrorEvent) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -333,13 +1030,14 @@ interface AudioContext extends EventTarget { createDynamicsCompressor(): DynamicsCompressorNode; createGain(): GainNode; createMediaElementSource(mediaElement: HTMLMediaElement): MediaElementAudioSourceNode; + createMediaStreamSource(mediaStream: MediaStream): MediaStreamAudioSourceNode; createOscillator(): OscillatorNode; createPanner(): PannerNode; - createPeriodicWave(real: Float32Array, imag: Float32Array): PeriodicWave; + createPeriodicWave(real: Float32Array, imag: Float32Array, constraints?: PeriodicWaveConstraints): PeriodicWave; createScriptProcessor(bufferSize?: number, numberOfInputChannels?: number, numberOfOutputChannels?: number): ScriptProcessorNode; createStereoPanner(): StereoPannerNode; createWaveShaper(): WaveShaperNode; - decodeAudioData(audioData: ArrayBuffer, successCallback: DecodeSuccessCallback, errorCallback?: DecodeErrorCallback): void; + decodeAudioData(audioData: ArrayBuffer, successCallback?: DecodeSuccessCallback, errorCallback?: DecodeErrorCallback): PromiseLike; } declare var AudioContext: { @@ -525,8 +1223,8 @@ declare var CSSFontFaceRule: { interface CSSGroupingRule extends CSSRule { cssRules: CSSRuleList; - deleteRule(index?: number): void; - insertRule(rule: string, index?: number): number; + deleteRule(index: number): void; + insertRule(rule: string, index: number): number; } declare var CSSGroupingRule: { @@ -881,7 +1579,6 @@ interface CSSStyleDeclaration { textAlignLast: string; textAnchor: string; textDecoration: string; - textFillColor: string; textIndent: string; textJustify: string; textKashida: string; @@ -917,25 +1614,12 @@ interface CSSStyleDeclaration { webkitAnimationTimingFunction: string; webkitAppearance: string; webkitBackfaceVisibility: string; - webkitBackground: string; - webkitBackgroundAttachment: string; webkitBackgroundClip: string; - webkitBackgroundColor: string; - webkitBackgroundImage: string; webkitBackgroundOrigin: string; - webkitBackgroundPosition: string; - webkitBackgroundPositionX: string; - webkitBackgroundPositionY: string; - webkitBackgroundRepeat: string; webkitBackgroundSize: string; webkitBorderBottomLeftRadius: string; webkitBorderBottomRightRadius: string; webkitBorderImage: string; - webkitBorderImageOutset: string; - webkitBorderImageRepeat: string; - webkitBorderImageSlice: string; - webkitBorderImageSource: string; - webkitBorderImageWidth: string; webkitBorderRadius: string; webkitBorderTopLeftRadius: string; webkitBorderTopRightRadius: string; @@ -981,6 +1665,7 @@ interface CSSStyleDeclaration { webkitTransitionDuration: string; webkitTransitionProperty: string; webkitTransitionTimingFunction: string; + webkitUserModify: string; webkitUserSelect: string; webkitWritingMode: string; whiteSpace: string; @@ -1068,7 +1753,7 @@ declare var CanvasPattern: { new(): CanvasPattern; } -interface CanvasRenderingContext2D { +interface CanvasRenderingContext2D extends Object, CanvasPathMethods { canvas: HTMLCanvasElement; fillStyle: string | CanvasGradient | CanvasPattern; font: string; @@ -1088,13 +1773,9 @@ interface CanvasRenderingContext2D { strokeStyle: string | CanvasGradient | CanvasPattern; textAlign: string; textBaseline: string; - arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, anticlockwise?: boolean): void; - arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void; beginPath(): void; - bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void; clearRect(x: number, y: number, w: number, h: number): void; clip(fillRule?: string): void; - closePath(): void; createImageData(imageDataOrSw: number | ImageData, sh?: number): ImageData; createLinearGradient(x0: number, y0: number, x1: number, y1: number): CanvasGradient; createPattern(image: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement, repetition: string): CanvasPattern; @@ -1106,12 +1787,8 @@ interface CanvasRenderingContext2D { getImageData(sx: number, sy: number, sw: number, sh: number): ImageData; getLineDash(): number[]; isPointInPath(x: number, y: number, fillRule?: string): boolean; - lineTo(x: number, y: number): void; measureText(text: string): TextMetrics; - moveTo(x: number, y: number): void; putImageData(imagedata: ImageData, dx: number, dy: number, dirtyX?: number, dirtyY?: number, dirtyWidth?: number, dirtyHeight?: number): void; - quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void; - rect(x: number, y: number, w: number, h: number): void; restore(): void; rotate(angle: number): void; save(): void; @@ -1246,6 +1923,7 @@ interface Console { dir(value?: any, ...optionalParams: any[]): void; dirxml(value: any): void; error(message?: any, ...optionalParams: any[]): void; + exception(message?: string, ...optionalParams: any[]): void; group(groupTitle?: string): void; groupCollapsed(groupTitle?: string): void; groupEnd(): void; @@ -1255,6 +1933,7 @@ interface Console { profile(reportName?: string): void; profileEnd(): void; select(element: Element): void; + table(...data: any[]): void; time(timerName?: string): void; timeEnd(timerName?: string): void; trace(message?: any, ...optionalParams: any[]): void; @@ -1559,6 +2238,15 @@ declare var DeviceAcceleration: { new(): DeviceAcceleration; } +interface DeviceLightEvent extends Event { + value: number; +} + +declare var DeviceLightEvent: { + prototype: DeviceLightEvent; + new(type: string, eventInitDict?: DeviceLightEventInit): DeviceLightEvent; +} + interface DeviceMotionEvent extends Event { acceleration: DeviceAcceleration; accelerationIncludingGravity: DeviceAcceleration; @@ -1616,7 +2304,7 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven /** * Returns a reference to the collection of elements contained by the object. */ - all: HTMLCollection; + all: HTMLAllCollection; /** * Retrieves a collection of all a objects that have a name and/or id property. Objects in this collection are in HTML source order. */ @@ -1643,6 +2331,7 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven */ compatMode: string; cookie: string; + currentScript: HTMLScriptElement | SVGScriptElement; /** * Gets the default character set from the current regional language settings. */ @@ -1712,11 +2401,8 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven * Contains information about the current URL. */ location: Location; - media: string; msCSSOMElementFloatMetrics: boolean; msCapsLockWarningOff: boolean; - msHidden: boolean; - msVisibilityState: string; /** * Fires when the user aborts the download. * @param ev The event. @@ -1818,7 +2504,7 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven * Occurs when the end of playback is reached. * @param ev The event */ - onended: (ev: Event) => any; + onended: (ev: MediaStreamErrorEvent) => any; /** * Fires when an error occurs during object loading. * @param ev The event. @@ -1832,6 +2518,7 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven onfullscreenchange: (ev: Event) => any; onfullscreenerror: (ev: Event) => any; oninput: (ev: Event) => any; + oninvalid: (ev: Event) => any; /** * Fires when the user presses a key. * @param ev The keyboard event @@ -1896,7 +2583,7 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven * Fires when the wheel button is rotated. * @param ev The mouse event */ - onmousewheel: (ev: MouseWheelEvent) => any; + onmousewheel: (ev: WheelEvent) => any; onmscontentzoom: (ev: UIEvent) => any; onmsgesturechange: (ev: MSGestureEvent) => any; onmsgesturedoubletap: (ev: MSGestureEvent) => any; @@ -1981,6 +2668,11 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven * @param ev The event. */ onselect: (ev: UIEvent) => any; + /** + * Fires when the selection state of a document changes. + * @param ev The event. + */ + onselectionchange: (ev: Event) => any; onselectstart: (ev: Event) => any; /** * Occurs when the download has stopped. @@ -2037,7 +2729,7 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven * Retrieves a collection of all script objects in the document. */ scripts: HTMLCollection; - security: string; + scrollingElement: Element; /** * Retrieves a collection of styleSheet objects representing the style sheets that correspond to each instance of a link or style object in the document. */ @@ -2061,9 +2753,9 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven * Gets or sets the version attribute specified in the declaration of an XML document. */ xmlVersion: string; - currentScript: HTMLScriptElement; adoptNode(source: Node): Node; captureEvents(): void; + caretRangeFromPoint(x: number, y: number): Range; clear(): void; /** * Closes an output stream and forces the sent data to display. @@ -2090,37 +2782,24 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven * @param tagName The name of an element. */ createElement(tagName: "a"): HTMLAnchorElement; - createElement(tagName: "abbr"): HTMLPhraseElement; - createElement(tagName: "acronym"): HTMLPhraseElement; - createElement(tagName: "address"): HTMLBlockElement; createElement(tagName: "applet"): HTMLAppletElement; createElement(tagName: "area"): HTMLAreaElement; createElement(tagName: "audio"): HTMLAudioElement; - createElement(tagName: "b"): HTMLPhraseElement; createElement(tagName: "base"): HTMLBaseElement; createElement(tagName: "basefont"): HTMLBaseFontElement; - createElement(tagName: "bdo"): HTMLPhraseElement; - createElement(tagName: "big"): HTMLPhraseElement; - createElement(tagName: "blockquote"): HTMLBlockElement; + createElement(tagName: "blockquote"): HTMLQuoteElement; createElement(tagName: "body"): HTMLBodyElement; createElement(tagName: "br"): HTMLBRElement; createElement(tagName: "button"): HTMLButtonElement; createElement(tagName: "canvas"): HTMLCanvasElement; createElement(tagName: "caption"): HTMLTableCaptionElement; - createElement(tagName: "center"): HTMLBlockElement; - createElement(tagName: "cite"): HTMLPhraseElement; - createElement(tagName: "code"): HTMLPhraseElement; createElement(tagName: "col"): HTMLTableColElement; createElement(tagName: "colgroup"): HTMLTableColElement; createElement(tagName: "datalist"): HTMLDataListElement; - createElement(tagName: "dd"): HTMLDDElement; createElement(tagName: "del"): HTMLModElement; - createElement(tagName: "dfn"): HTMLPhraseElement; createElement(tagName: "dir"): HTMLDirectoryElement; createElement(tagName: "div"): HTMLDivElement; createElement(tagName: "dl"): HTMLDListElement; - createElement(tagName: "dt"): HTMLDTElement; - createElement(tagName: "em"): HTMLPhraseElement; createElement(tagName: "embed"): HTMLEmbedElement; createElement(tagName: "fieldset"): HTMLFieldSetElement; createElement(tagName: "font"): HTMLFontElement; @@ -2136,52 +2815,41 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven createElement(tagName: "head"): HTMLHeadElement; createElement(tagName: "hr"): HTMLHRElement; createElement(tagName: "html"): HTMLHtmlElement; - createElement(tagName: "i"): HTMLPhraseElement; createElement(tagName: "iframe"): HTMLIFrameElement; createElement(tagName: "img"): HTMLImageElement; createElement(tagName: "input"): HTMLInputElement; createElement(tagName: "ins"): HTMLModElement; - createElement(tagName: "isindex"): HTMLIsIndexElement; - createElement(tagName: "kbd"): HTMLPhraseElement; - createElement(tagName: "keygen"): HTMLBlockElement; + createElement(tagName: "isindex"): HTMLUnknownElement; createElement(tagName: "label"): HTMLLabelElement; createElement(tagName: "legend"): HTMLLegendElement; createElement(tagName: "li"): HTMLLIElement; createElement(tagName: "link"): HTMLLinkElement; - createElement(tagName: "listing"): HTMLBlockElement; + createElement(tagName: "listing"): HTMLPreElement; createElement(tagName: "map"): HTMLMapElement; createElement(tagName: "marquee"): HTMLMarqueeElement; createElement(tagName: "menu"): HTMLMenuElement; createElement(tagName: "meta"): HTMLMetaElement; - createElement(tagName: "nextid"): HTMLNextIdElement; - createElement(tagName: "nobr"): HTMLPhraseElement; + createElement(tagName: "meter"): HTMLMeterElement; + createElement(tagName: "nextid"): HTMLUnknownElement; createElement(tagName: "object"): HTMLObjectElement; createElement(tagName: "ol"): HTMLOListElement; createElement(tagName: "optgroup"): HTMLOptGroupElement; createElement(tagName: "option"): HTMLOptionElement; createElement(tagName: "p"): HTMLParagraphElement; createElement(tagName: "param"): HTMLParamElement; - createElement(tagName: "plaintext"): HTMLBlockElement; + createElement(tagName: "picture"): HTMLPictureElement; createElement(tagName: "pre"): HTMLPreElement; createElement(tagName: "progress"): HTMLProgressElement; createElement(tagName: "q"): HTMLQuoteElement; - createElement(tagName: "rt"): HTMLPhraseElement; - createElement(tagName: "ruby"): HTMLPhraseElement; - createElement(tagName: "s"): HTMLPhraseElement; - createElement(tagName: "samp"): HTMLPhraseElement; createElement(tagName: "script"): HTMLScriptElement; createElement(tagName: "select"): HTMLSelectElement; - createElement(tagName: "small"): HTMLPhraseElement; createElement(tagName: "source"): HTMLSourceElement; createElement(tagName: "span"): HTMLSpanElement; - createElement(tagName: "strike"): HTMLPhraseElement; - createElement(tagName: "strong"): HTMLPhraseElement; createElement(tagName: "style"): HTMLStyleElement; - createElement(tagName: "sub"): HTMLPhraseElement; - createElement(tagName: "sup"): HTMLPhraseElement; createElement(tagName: "table"): HTMLTableElement; createElement(tagName: "tbody"): HTMLTableSectionElement; createElement(tagName: "td"): HTMLTableDataCellElement; + createElement(tagName: "template"): HTMLTemplateElement; createElement(tagName: "textarea"): HTMLTextAreaElement; createElement(tagName: "tfoot"): HTMLTableSectionElement; createElement(tagName: "th"): HTMLTableHeaderCellElement; @@ -2189,13 +2857,10 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven createElement(tagName: "title"): HTMLTitleElement; createElement(tagName: "tr"): HTMLTableRowElement; createElement(tagName: "track"): HTMLTrackElement; - createElement(tagName: "tt"): HTMLPhraseElement; - createElement(tagName: "u"): HTMLPhraseElement; createElement(tagName: "ul"): HTMLUListElement; - createElement(tagName: "var"): HTMLPhraseElement; createElement(tagName: "video"): HTMLVideoElement; createElement(tagName: "x-ms-webview"): MSHTMLWebViewElement; - createElement(tagName: "xmp"): HTMLBlockElement; + createElement(tagName: "xmp"): HTMLPreElement; createElement(tagName: string): HTMLElement; createElementNS(namespaceURI: "http://www.w3.org/2000/svg", qualifiedName: "a"): SVGAElement createElementNS(namespaceURI: "http://www.w3.org/2000/svg", qualifiedName: "circle"): SVGCircleElement @@ -2280,7 +2945,7 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven * @param data String that specifies the nodeValue property of the text node. */ createTextNode(data: string): Text; - createTouch(view: any, target: EventTarget, identifier: number, pageX: number, pageY: number, screenX: number, screenY: number): Touch; + createTouch(view: Window, target: EventTarget, identifier: number, pageX: number, pageY: number, screenX: number, screenY: number): Touch; createTouchList(...touches: Touch[]): TouchList; /** * Creates a TreeWalker object that you can use to traverse filtered lists of nodes or elements in a document. @@ -2331,44 +2996,44 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven * @param name Specifies the name of an element. */ getElementsByTagName(tagname: "a"): NodeListOf; - getElementsByTagName(tagname: "abbr"): NodeListOf; - getElementsByTagName(tagname: "acronym"): NodeListOf; - getElementsByTagName(tagname: "address"): NodeListOf; + getElementsByTagName(tagname: "abbr"): NodeListOf; + getElementsByTagName(tagname: "acronym"): NodeListOf; + getElementsByTagName(tagname: "address"): NodeListOf; getElementsByTagName(tagname: "applet"): NodeListOf; getElementsByTagName(tagname: "area"): NodeListOf; getElementsByTagName(tagname: "article"): NodeListOf; getElementsByTagName(tagname: "aside"): NodeListOf; getElementsByTagName(tagname: "audio"): NodeListOf; - getElementsByTagName(tagname: "b"): NodeListOf; + getElementsByTagName(tagname: "b"): NodeListOf; getElementsByTagName(tagname: "base"): NodeListOf; getElementsByTagName(tagname: "basefont"): NodeListOf; - getElementsByTagName(tagname: "bdo"): NodeListOf; - getElementsByTagName(tagname: "big"): NodeListOf; - getElementsByTagName(tagname: "blockquote"): NodeListOf; + getElementsByTagName(tagname: "bdo"): NodeListOf; + getElementsByTagName(tagname: "big"): NodeListOf; + getElementsByTagName(tagname: "blockquote"): NodeListOf; getElementsByTagName(tagname: "body"): NodeListOf; getElementsByTagName(tagname: "br"): NodeListOf; getElementsByTagName(tagname: "button"): NodeListOf; getElementsByTagName(tagname: "canvas"): NodeListOf; getElementsByTagName(tagname: "caption"): NodeListOf; - getElementsByTagName(tagname: "center"): NodeListOf; + getElementsByTagName(tagname: "center"): NodeListOf; getElementsByTagName(tagname: "circle"): NodeListOf; - getElementsByTagName(tagname: "cite"): NodeListOf; + getElementsByTagName(tagname: "cite"): NodeListOf; getElementsByTagName(tagname: "clippath"): NodeListOf; - getElementsByTagName(tagname: "code"): NodeListOf; + getElementsByTagName(tagname: "code"): NodeListOf; getElementsByTagName(tagname: "col"): NodeListOf; getElementsByTagName(tagname: "colgroup"): NodeListOf; getElementsByTagName(tagname: "datalist"): NodeListOf; - getElementsByTagName(tagname: "dd"): NodeListOf; + getElementsByTagName(tagname: "dd"): NodeListOf; getElementsByTagName(tagname: "defs"): NodeListOf; getElementsByTagName(tagname: "del"): NodeListOf; getElementsByTagName(tagname: "desc"): NodeListOf; - getElementsByTagName(tagname: "dfn"): NodeListOf; + getElementsByTagName(tagname: "dfn"): NodeListOf; getElementsByTagName(tagname: "dir"): NodeListOf; getElementsByTagName(tagname: "div"): NodeListOf; getElementsByTagName(tagname: "dl"): NodeListOf; - getElementsByTagName(tagname: "dt"): NodeListOf; + getElementsByTagName(tagname: "dt"): NodeListOf; getElementsByTagName(tagname: "ellipse"): NodeListOf; - getElementsByTagName(tagname: "em"): NodeListOf; + getElementsByTagName(tagname: "em"): NodeListOf; getElementsByTagName(tagname: "embed"): NodeListOf; getElementsByTagName(tagname: "feblend"): NodeListOf; getElementsByTagName(tagname: "fecolormatrix"): NodeListOf; @@ -2416,22 +3081,22 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven getElementsByTagName(tagname: "hgroup"): NodeListOf; getElementsByTagName(tagname: "hr"): NodeListOf; getElementsByTagName(tagname: "html"): NodeListOf; - getElementsByTagName(tagname: "i"): NodeListOf; + getElementsByTagName(tagname: "i"): NodeListOf; getElementsByTagName(tagname: "iframe"): NodeListOf; getElementsByTagName(tagname: "image"): NodeListOf; getElementsByTagName(tagname: "img"): NodeListOf; getElementsByTagName(tagname: "input"): NodeListOf; getElementsByTagName(tagname: "ins"): NodeListOf; - getElementsByTagName(tagname: "isindex"): NodeListOf; - getElementsByTagName(tagname: "kbd"): NodeListOf; - getElementsByTagName(tagname: "keygen"): NodeListOf; + getElementsByTagName(tagname: "isindex"): NodeListOf; + getElementsByTagName(tagname: "kbd"): NodeListOf; + getElementsByTagName(tagname: "keygen"): NodeListOf; getElementsByTagName(tagname: "label"): NodeListOf; getElementsByTagName(tagname: "legend"): NodeListOf; getElementsByTagName(tagname: "li"): NodeListOf; getElementsByTagName(tagname: "line"): NodeListOf; getElementsByTagName(tagname: "lineargradient"): NodeListOf; getElementsByTagName(tagname: "link"): NodeListOf; - getElementsByTagName(tagname: "listing"): NodeListOf; + getElementsByTagName(tagname: "listing"): NodeListOf; getElementsByTagName(tagname: "map"): NodeListOf; getElementsByTagName(tagname: "mark"): NodeListOf; getElementsByTagName(tagname: "marker"): NodeListOf; @@ -2440,9 +3105,10 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven getElementsByTagName(tagname: "menu"): NodeListOf; getElementsByTagName(tagname: "meta"): NodeListOf; getElementsByTagName(tagname: "metadata"): NodeListOf; + getElementsByTagName(tagname: "meter"): NodeListOf; getElementsByTagName(tagname: "nav"): NodeListOf; - getElementsByTagName(tagname: "nextid"): NodeListOf; - getElementsByTagName(tagname: "nobr"): NodeListOf; + getElementsByTagName(tagname: "nextid"): NodeListOf; + getElementsByTagName(tagname: "nobr"): NodeListOf; getElementsByTagName(tagname: "noframes"): NodeListOf; getElementsByTagName(tagname: "noscript"): NodeListOf; getElementsByTagName(tagname: "object"): NodeListOf; @@ -2453,7 +3119,8 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven getElementsByTagName(tagname: "param"): NodeListOf; getElementsByTagName(tagname: "path"): NodeListOf; getElementsByTagName(tagname: "pattern"): NodeListOf; - getElementsByTagName(tagname: "plaintext"): NodeListOf; + getElementsByTagName(tagname: "picture"): NodeListOf; + getElementsByTagName(tagname: "plaintext"): NodeListOf; getElementsByTagName(tagname: "polygon"): NodeListOf; getElementsByTagName(tagname: "polyline"): NodeListOf; getElementsByTagName(tagname: "pre"): NodeListOf; @@ -2461,28 +3128,29 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven getElementsByTagName(tagname: "q"): NodeListOf; getElementsByTagName(tagname: "radialgradient"): NodeListOf; getElementsByTagName(tagname: "rect"): NodeListOf; - getElementsByTagName(tagname: "rt"): NodeListOf; - getElementsByTagName(tagname: "ruby"): NodeListOf; - getElementsByTagName(tagname: "s"): NodeListOf; - getElementsByTagName(tagname: "samp"): NodeListOf; + getElementsByTagName(tagname: "rt"): NodeListOf; + getElementsByTagName(tagname: "ruby"): NodeListOf; + getElementsByTagName(tagname: "s"): NodeListOf; + getElementsByTagName(tagname: "samp"): NodeListOf; getElementsByTagName(tagname: "script"): NodeListOf; getElementsByTagName(tagname: "section"): NodeListOf; getElementsByTagName(tagname: "select"): NodeListOf; - getElementsByTagName(tagname: "small"): NodeListOf; + getElementsByTagName(tagname: "small"): NodeListOf; getElementsByTagName(tagname: "source"): NodeListOf; getElementsByTagName(tagname: "span"): NodeListOf; getElementsByTagName(tagname: "stop"): NodeListOf; - getElementsByTagName(tagname: "strike"): NodeListOf; - getElementsByTagName(tagname: "strong"): NodeListOf; + getElementsByTagName(tagname: "strike"): NodeListOf; + getElementsByTagName(tagname: "strong"): NodeListOf; getElementsByTagName(tagname: "style"): NodeListOf; - getElementsByTagName(tagname: "sub"): NodeListOf; - getElementsByTagName(tagname: "sup"): NodeListOf; + getElementsByTagName(tagname: "sub"): NodeListOf; + getElementsByTagName(tagname: "sup"): NodeListOf; getElementsByTagName(tagname: "svg"): NodeListOf; getElementsByTagName(tagname: "switch"): NodeListOf; getElementsByTagName(tagname: "symbol"): NodeListOf; getElementsByTagName(tagname: "table"): NodeListOf; getElementsByTagName(tagname: "tbody"): NodeListOf; getElementsByTagName(tagname: "td"): NodeListOf; + getElementsByTagName(tagname: "template"): NodeListOf; getElementsByTagName(tagname: "text"): NodeListOf; getElementsByTagName(tagname: "textpath"): NodeListOf; getElementsByTagName(tagname: "textarea"): NodeListOf; @@ -2493,16 +3161,16 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven getElementsByTagName(tagname: "tr"): NodeListOf; getElementsByTagName(tagname: "track"): NodeListOf; getElementsByTagName(tagname: "tspan"): NodeListOf; - getElementsByTagName(tagname: "tt"): NodeListOf; - getElementsByTagName(tagname: "u"): NodeListOf; + getElementsByTagName(tagname: "tt"): NodeListOf; + getElementsByTagName(tagname: "u"): NodeListOf; getElementsByTagName(tagname: "ul"): NodeListOf; getElementsByTagName(tagname: "use"): NodeListOf; - getElementsByTagName(tagname: "var"): NodeListOf; + getElementsByTagName(tagname: "var"): NodeListOf; getElementsByTagName(tagname: "video"): NodeListOf; getElementsByTagName(tagname: "view"): NodeListOf; getElementsByTagName(tagname: "wbr"): NodeListOf; getElementsByTagName(tagname: "x-ms-webview"): NodeListOf; - getElementsByTagName(tagname: "xmp"): NodeListOf; + getElementsByTagName(tagname: "xmp"): NodeListOf; getElementsByTagName(tagname: string): NodeListOf; getElementsByTagNameNS(namespaceURI: string, localName: string): NodeListOf; /** @@ -2611,12 +3279,13 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void; addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void; - addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "ended", listener: (ev: MediaStreamErrorEvent) => any, useCapture?: boolean): void; addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void; addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void; addEventListener(type: "fullscreenchange", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "fullscreenerror", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "invalid", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; @@ -2629,7 +3298,7 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; - addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void; + addEventListener(type: "mousewheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void; addEventListener(type: "mssitemodejumplistitemremoved", listener: (ev: MSSiteModeEvent) => any, useCapture?: boolean): void; addEventListener(type: "msthumbnailclick", listener: (ev: MSSiteModeEvent) => any, useCapture?: boolean): void; addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void; @@ -2653,6 +3322,7 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven addEventListener(type: "seeked", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "seeking", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "select", listener: (ev: UIEvent) => any, useCapture?: boolean): void; + addEventListener(type: "selectionchange", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "selectstart", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "stalled", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "stop", listener: (ev: Event) => any, useCapture?: boolean): void; @@ -2725,6 +3395,14 @@ declare var DynamicsCompressorNode: { new(): DynamicsCompressorNode; } +interface EXT_frag_depth { +} + +declare var EXT_frag_depth: { + prototype: EXT_frag_depth; + new(): EXT_frag_depth; +} + interface EXT_texture_filter_anisotropic { MAX_TEXTURE_MAX_ANISOTROPY_EXT: number; TEXTURE_MAX_ANISOTROPY_EXT: number; @@ -2739,10 +3417,12 @@ declare var EXT_texture_filter_anisotropic: { interface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelector, ChildNode { classList: DOMTokenList; + className: string; clientHeight: number; clientLeft: number; clientTop: number; clientWidth: number; + id: string; msContentZoomFactor: number; msRegionOverflow: string; onariarequest: (ev: AriaRequestEvent) => any; @@ -2772,13 +3452,12 @@ interface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelec ontouchstart: (ev: TouchEvent) => any; onwebkitfullscreenchange: (ev: Event) => any; onwebkitfullscreenerror: (ev: Event) => any; + prefix: string; scrollHeight: number; scrollLeft: number; scrollTop: number; scrollWidth: number; tagName: string; - id: string; - className: string; innerHTML: string; getAttribute(name?: string): string; getAttributeNS(namespaceURI: string, localName: string): string; @@ -2787,44 +3466,44 @@ interface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelec getBoundingClientRect(): ClientRect; getClientRects(): ClientRectList; getElementsByTagName(name: "a"): NodeListOf; - getElementsByTagName(name: "abbr"): NodeListOf; - getElementsByTagName(name: "acronym"): NodeListOf; - getElementsByTagName(name: "address"): NodeListOf; + getElementsByTagName(name: "abbr"): NodeListOf; + getElementsByTagName(name: "acronym"): NodeListOf; + getElementsByTagName(name: "address"): NodeListOf; getElementsByTagName(name: "applet"): NodeListOf; getElementsByTagName(name: "area"): NodeListOf; getElementsByTagName(name: "article"): NodeListOf; getElementsByTagName(name: "aside"): NodeListOf; getElementsByTagName(name: "audio"): NodeListOf; - getElementsByTagName(name: "b"): NodeListOf; + getElementsByTagName(name: "b"): NodeListOf; getElementsByTagName(name: "base"): NodeListOf; getElementsByTagName(name: "basefont"): NodeListOf; - getElementsByTagName(name: "bdo"): NodeListOf; - getElementsByTagName(name: "big"): NodeListOf; - getElementsByTagName(name: "blockquote"): NodeListOf; + getElementsByTagName(name: "bdo"): NodeListOf; + getElementsByTagName(name: "big"): NodeListOf; + getElementsByTagName(name: "blockquote"): NodeListOf; getElementsByTagName(name: "body"): NodeListOf; getElementsByTagName(name: "br"): NodeListOf; getElementsByTagName(name: "button"): NodeListOf; getElementsByTagName(name: "canvas"): NodeListOf; getElementsByTagName(name: "caption"): NodeListOf; - getElementsByTagName(name: "center"): NodeListOf; + getElementsByTagName(name: "center"): NodeListOf; getElementsByTagName(name: "circle"): NodeListOf; - getElementsByTagName(name: "cite"): NodeListOf; + getElementsByTagName(name: "cite"): NodeListOf; getElementsByTagName(name: "clippath"): NodeListOf; - getElementsByTagName(name: "code"): NodeListOf; + getElementsByTagName(name: "code"): NodeListOf; getElementsByTagName(name: "col"): NodeListOf; getElementsByTagName(name: "colgroup"): NodeListOf; getElementsByTagName(name: "datalist"): NodeListOf; - getElementsByTagName(name: "dd"): NodeListOf; + getElementsByTagName(name: "dd"): NodeListOf; getElementsByTagName(name: "defs"): NodeListOf; getElementsByTagName(name: "del"): NodeListOf; getElementsByTagName(name: "desc"): NodeListOf; - getElementsByTagName(name: "dfn"): NodeListOf; + getElementsByTagName(name: "dfn"): NodeListOf; getElementsByTagName(name: "dir"): NodeListOf; getElementsByTagName(name: "div"): NodeListOf; getElementsByTagName(name: "dl"): NodeListOf; - getElementsByTagName(name: "dt"): NodeListOf; + getElementsByTagName(name: "dt"): NodeListOf; getElementsByTagName(name: "ellipse"): NodeListOf; - getElementsByTagName(name: "em"): NodeListOf; + getElementsByTagName(name: "em"): NodeListOf; getElementsByTagName(name: "embed"): NodeListOf; getElementsByTagName(name: "feblend"): NodeListOf; getElementsByTagName(name: "fecolormatrix"): NodeListOf; @@ -2872,22 +3551,22 @@ interface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelec getElementsByTagName(name: "hgroup"): NodeListOf; getElementsByTagName(name: "hr"): NodeListOf; getElementsByTagName(name: "html"): NodeListOf; - getElementsByTagName(name: "i"): NodeListOf; + getElementsByTagName(name: "i"): NodeListOf; getElementsByTagName(name: "iframe"): NodeListOf; getElementsByTagName(name: "image"): NodeListOf; getElementsByTagName(name: "img"): NodeListOf; getElementsByTagName(name: "input"): NodeListOf; getElementsByTagName(name: "ins"): NodeListOf; - getElementsByTagName(name: "isindex"): NodeListOf; - getElementsByTagName(name: "kbd"): NodeListOf; - getElementsByTagName(name: "keygen"): NodeListOf; + getElementsByTagName(name: "isindex"): NodeListOf; + getElementsByTagName(name: "kbd"): NodeListOf; + getElementsByTagName(name: "keygen"): NodeListOf; getElementsByTagName(name: "label"): NodeListOf; getElementsByTagName(name: "legend"): NodeListOf; getElementsByTagName(name: "li"): NodeListOf; getElementsByTagName(name: "line"): NodeListOf; getElementsByTagName(name: "lineargradient"): NodeListOf; getElementsByTagName(name: "link"): NodeListOf; - getElementsByTagName(name: "listing"): NodeListOf; + getElementsByTagName(name: "listing"): NodeListOf; getElementsByTagName(name: "map"): NodeListOf; getElementsByTagName(name: "mark"): NodeListOf; getElementsByTagName(name: "marker"): NodeListOf; @@ -2896,9 +3575,10 @@ interface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelec getElementsByTagName(name: "menu"): NodeListOf; getElementsByTagName(name: "meta"): NodeListOf; getElementsByTagName(name: "metadata"): NodeListOf; + getElementsByTagName(name: "meter"): NodeListOf; getElementsByTagName(name: "nav"): NodeListOf; - getElementsByTagName(name: "nextid"): NodeListOf; - getElementsByTagName(name: "nobr"): NodeListOf; + getElementsByTagName(name: "nextid"): NodeListOf; + getElementsByTagName(name: "nobr"): NodeListOf; getElementsByTagName(name: "noframes"): NodeListOf; getElementsByTagName(name: "noscript"): NodeListOf; getElementsByTagName(name: "object"): NodeListOf; @@ -2909,7 +3589,8 @@ interface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelec getElementsByTagName(name: "param"): NodeListOf; getElementsByTagName(name: "path"): NodeListOf; getElementsByTagName(name: "pattern"): NodeListOf; - getElementsByTagName(name: "plaintext"): NodeListOf; + getElementsByTagName(name: "picture"): NodeListOf; + getElementsByTagName(name: "plaintext"): NodeListOf; getElementsByTagName(name: "polygon"): NodeListOf; getElementsByTagName(name: "polyline"): NodeListOf; getElementsByTagName(name: "pre"): NodeListOf; @@ -2917,28 +3598,29 @@ interface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelec getElementsByTagName(name: "q"): NodeListOf; getElementsByTagName(name: "radialgradient"): NodeListOf; getElementsByTagName(name: "rect"): NodeListOf; - getElementsByTagName(name: "rt"): NodeListOf; - getElementsByTagName(name: "ruby"): NodeListOf; - getElementsByTagName(name: "s"): NodeListOf; - getElementsByTagName(name: "samp"): NodeListOf; + getElementsByTagName(name: "rt"): NodeListOf; + getElementsByTagName(name: "ruby"): NodeListOf; + getElementsByTagName(name: "s"): NodeListOf; + getElementsByTagName(name: "samp"): NodeListOf; getElementsByTagName(name: "script"): NodeListOf; getElementsByTagName(name: "section"): NodeListOf; getElementsByTagName(name: "select"): NodeListOf; - getElementsByTagName(name: "small"): NodeListOf; + getElementsByTagName(name: "small"): NodeListOf; getElementsByTagName(name: "source"): NodeListOf; getElementsByTagName(name: "span"): NodeListOf; getElementsByTagName(name: "stop"): NodeListOf; - getElementsByTagName(name: "strike"): NodeListOf; - getElementsByTagName(name: "strong"): NodeListOf; + getElementsByTagName(name: "strike"): NodeListOf; + getElementsByTagName(name: "strong"): NodeListOf; getElementsByTagName(name: "style"): NodeListOf; - getElementsByTagName(name: "sub"): NodeListOf; - getElementsByTagName(name: "sup"): NodeListOf; + getElementsByTagName(name: "sub"): NodeListOf; + getElementsByTagName(name: "sup"): NodeListOf; getElementsByTagName(name: "svg"): NodeListOf; getElementsByTagName(name: "switch"): NodeListOf; getElementsByTagName(name: "symbol"): NodeListOf; getElementsByTagName(name: "table"): NodeListOf; getElementsByTagName(name: "tbody"): NodeListOf; getElementsByTagName(name: "td"): NodeListOf; + getElementsByTagName(name: "template"): NodeListOf; getElementsByTagName(name: "text"): NodeListOf; getElementsByTagName(name: "textpath"): NodeListOf; getElementsByTagName(name: "textarea"): NodeListOf; @@ -2949,16 +3631,16 @@ interface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelec getElementsByTagName(name: "tr"): NodeListOf; getElementsByTagName(name: "track"): NodeListOf; getElementsByTagName(name: "tspan"): NodeListOf; - getElementsByTagName(name: "tt"): NodeListOf; - getElementsByTagName(name: "u"): NodeListOf; + getElementsByTagName(name: "tt"): NodeListOf; + getElementsByTagName(name: "u"): NodeListOf; getElementsByTagName(name: "ul"): NodeListOf; getElementsByTagName(name: "use"): NodeListOf; - getElementsByTagName(name: "var"): NodeListOf; + getElementsByTagName(name: "var"): NodeListOf; getElementsByTagName(name: "video"): NodeListOf; getElementsByTagName(name: "view"): NodeListOf; getElementsByTagName(name: "wbr"): NodeListOf; getElementsByTagName(name: "x-ms-webview"): NodeListOf; - getElementsByTagName(name: "xmp"): NodeListOf; + getElementsByTagName(name: "xmp"): NodeListOf; getElementsByTagName(name: string): NodeListOf; getElementsByTagNameNS(namespaceURI: string, localName: string): NodeListOf; hasAttribute(name: string): boolean; @@ -3075,9 +3757,9 @@ declare var Event: { } interface EventTarget { - addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; + addEventListener(type: string, listener?: EventListenerOrEventListenerObject, useCapture?: boolean): void; dispatchEvent(evt: Event): boolean; - removeEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; + removeEventListener(type: string, listener?: EventListenerOrEventListenerObject, useCapture?: boolean): void; } declare var EventTarget: { @@ -3096,6 +3778,7 @@ declare var External: { interface File extends Blob { lastModifiedDate: any; name: string; + webkitRelativePath: string; } declare var File: { @@ -3220,6 +3903,7 @@ interface HTMLAnchorElement extends HTMLElement { * Sets or retrieves the coordinates of the object. */ coords: string; + download: string; /** * Contains the anchor portion of the URL including the hash sign (#). */ @@ -3377,6 +4061,7 @@ interface HTMLAreaElement extends HTMLElement { * Sets or retrieves the coordinates of the object. */ coords: string; + download: string; /** * Sets or retrieves the subsection of the href property that follows the number sign (#). */ @@ -3502,23 +4187,6 @@ declare var HTMLBaseFontElement: { new(): HTMLBaseFontElement; } -interface HTMLBlockElement extends HTMLElement { - /** - * Sets or retrieves reference information about the object. - */ - cite: string; - clear: string; - /** - * Sets or retrieves the width of the object. - */ - width: number; -} - -declare var HTMLBlockElement: { - prototype: HTMLBlockElement; - new(): HTMLBlockElement; -} - interface HTMLBodyElement extends HTMLElement { aLink: any; background: string; @@ -3546,7 +4214,6 @@ interface HTMLBodyElement extends HTMLElement { onunload: (ev: Event) => any; text: any; vLink: any; - createTextRange(): TextRange; addEventListener(type: "MSContentZoom", listener: (ev: UIEvent) => any, useCapture?: boolean): void; addEventListener(type: "MSGestureChange", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void; addEventListener(type: "MSGestureDoubleTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void; @@ -3571,10 +4238,10 @@ interface HTMLBodyElement extends HTMLElement { addEventListener(type: "afterprint", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "ariarequest", listener: (ev: AriaRequestEvent) => any, useCapture?: boolean): void; addEventListener(type: "beforeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; - addEventListener(type: "beforecopy", listener: (ev: DragEvent) => any, useCapture?: boolean): void; - addEventListener(type: "beforecut", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "beforecopy", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; + addEventListener(type: "beforecut", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "beforedeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; - addEventListener(type: "beforepaste", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "beforepaste", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "beforeprint", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "beforeunload", listener: (ev: BeforeUnloadEvent) => any, useCapture?: boolean): void; addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void; @@ -3585,9 +4252,9 @@ interface HTMLBodyElement extends HTMLElement { addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "command", listener: (ev: CommandEvent) => any, useCapture?: boolean): void; addEventListener(type: "contextmenu", listener: (ev: PointerEvent) => any, useCapture?: boolean): void; - addEventListener(type: "copy", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "copy", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "cuechange", listener: (ev: Event) => any, useCapture?: boolean): void; - addEventListener(type: "cut", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "cut", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "deactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void; @@ -3599,7 +4266,7 @@ interface HTMLBodyElement extends HTMLElement { addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void; addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void; - addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "ended", listener: (ev: MediaStreamErrorEvent) => any, useCapture?: boolean): void; addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void; addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void; addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void; @@ -3607,6 +4274,7 @@ interface HTMLBodyElement extends HTMLElement { addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void; addEventListener(type: "hashchange", listener: (ev: HashChangeEvent) => any, useCapture?: boolean): void; addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "invalid", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; @@ -3624,13 +4292,13 @@ interface HTMLBodyElement extends HTMLElement { addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; - addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void; + addEventListener(type: "mousewheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void; addEventListener(type: "offline", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "online", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "orientationchange", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "pagehide", listener: (ev: PageTransitionEvent) => any, useCapture?: boolean): void; addEventListener(type: "pageshow", listener: (ev: PageTransitionEvent) => any, useCapture?: boolean): void; - addEventListener(type: "paste", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "paste", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void; @@ -3734,10 +4402,6 @@ interface HTMLButtonElement extends HTMLElement { * Returns whether a form will validate when it is submitted, without having to submit it. */ checkValidity(): boolean; - /** - * Creates a TextRange object for the element. - */ - createTextRange(): TextRange; /** * Sets a custom error message that is displayed when a form is submitted. * @param error Sets a custom error message that is displayed when a form is submitted. @@ -3804,18 +4468,6 @@ declare var HTMLCollection: { new(): HTMLCollection; } -interface HTMLDDElement extends HTMLElement { - /** - * Sets or retrieves whether the browser automatically performs wordwrap. - */ - noWrap: boolean; -} - -declare var HTMLDDElement: { - prototype: HTMLDDElement; - new(): HTMLDDElement; -} - interface HTMLDListElement extends HTMLElement { compact: boolean; } @@ -3825,18 +4477,6 @@ declare var HTMLDListElement: { new(): HTMLDListElement; } -interface HTMLDTElement extends HTMLElement { - /** - * Sets or retrieves whether the browser automatically performs wordwrap. - */ - noWrap: boolean; -} - -declare var HTMLDTElement: { - prototype: HTMLDTElement; - new(): HTMLDTElement; -} - interface HTMLDataListElement extends HTMLElement { options: HTMLCollection; } @@ -3900,19 +4540,19 @@ interface HTMLElement extends Element { onabort: (ev: Event) => any; onactivate: (ev: UIEvent) => any; onbeforeactivate: (ev: UIEvent) => any; - onbeforecopy: (ev: DragEvent) => any; - onbeforecut: (ev: DragEvent) => any; + onbeforecopy: (ev: ClipboardEvent) => any; + onbeforecut: (ev: ClipboardEvent) => any; onbeforedeactivate: (ev: UIEvent) => any; - onbeforepaste: (ev: DragEvent) => any; + onbeforepaste: (ev: ClipboardEvent) => any; onblur: (ev: FocusEvent) => any; oncanplay: (ev: Event) => any; oncanplaythrough: (ev: Event) => any; onchange: (ev: Event) => any; onclick: (ev: MouseEvent) => any; oncontextmenu: (ev: PointerEvent) => any; - oncopy: (ev: DragEvent) => any; + oncopy: (ev: ClipboardEvent) => any; oncuechange: (ev: Event) => any; - oncut: (ev: DragEvent) => any; + oncut: (ev: ClipboardEvent) => any; ondblclick: (ev: MouseEvent) => any; ondeactivate: (ev: UIEvent) => any; ondrag: (ev: DragEvent) => any; @@ -3924,10 +4564,11 @@ interface HTMLElement extends Element { ondrop: (ev: DragEvent) => any; ondurationchange: (ev: Event) => any; onemptied: (ev: Event) => any; - onended: (ev: Event) => any; + onended: (ev: MediaStreamErrorEvent) => any; onerror: (ev: Event) => any; onfocus: (ev: FocusEvent) => any; oninput: (ev: Event) => any; + oninvalid: (ev: Event) => any; onkeydown: (ev: KeyboardEvent) => any; onkeypress: (ev: KeyboardEvent) => any; onkeyup: (ev: KeyboardEvent) => any; @@ -3942,10 +4583,10 @@ interface HTMLElement extends Element { onmouseout: (ev: MouseEvent) => any; onmouseover: (ev: MouseEvent) => any; onmouseup: (ev: MouseEvent) => any; - onmousewheel: (ev: MouseWheelEvent) => any; + onmousewheel: (ev: WheelEvent) => any; onmscontentzoom: (ev: UIEvent) => any; onmsmanipulationstatechanged: (ev: MSManipulationEvent) => any; - onpaste: (ev: DragEvent) => any; + onpaste: (ev: ClipboardEvent) => any; onpause: (ev: Event) => any; onplay: (ev: Event) => any; onplaying: (ev: Event) => any; @@ -4002,10 +4643,10 @@ interface HTMLElement extends Element { addEventListener(type: "activate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; addEventListener(type: "ariarequest", listener: (ev: AriaRequestEvent) => any, useCapture?: boolean): void; addEventListener(type: "beforeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; - addEventListener(type: "beforecopy", listener: (ev: DragEvent) => any, useCapture?: boolean): void; - addEventListener(type: "beforecut", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "beforecopy", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; + addEventListener(type: "beforecut", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "beforedeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; - addEventListener(type: "beforepaste", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "beforepaste", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void; addEventListener(type: "canplay", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "canplaythrough", listener: (ev: Event) => any, useCapture?: boolean): void; @@ -4013,9 +4654,9 @@ interface HTMLElement extends Element { addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "command", listener: (ev: CommandEvent) => any, useCapture?: boolean): void; addEventListener(type: "contextmenu", listener: (ev: PointerEvent) => any, useCapture?: boolean): void; - addEventListener(type: "copy", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "copy", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "cuechange", listener: (ev: Event) => any, useCapture?: boolean): void; - addEventListener(type: "cut", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "cut", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "deactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void; @@ -4027,11 +4668,12 @@ interface HTMLElement extends Element { addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void; addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void; - addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "ended", listener: (ev: MediaStreamErrorEvent) => any, useCapture?: boolean): void; addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void; addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void; addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void; addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "invalid", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; @@ -4047,8 +4689,8 @@ interface HTMLElement extends Element { addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; - addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void; - addEventListener(type: "paste", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "mousewheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void; + addEventListener(type: "paste", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void; @@ -4327,10 +4969,6 @@ interface HTMLFrameElement extends HTMLElement, GetSVGDocument { * Sets or retrieves whether the frame can be scrolled. */ scrolling: string; - /** - * Sets the value indicating whether the source file of a frame or iframe has specific security restrictions applied. - */ - security: any; /** * Sets or retrieves a URL to be loaded by the object. */ @@ -4362,10 +5000,10 @@ interface HTMLFrameElement extends HTMLElement, GetSVGDocument { addEventListener(type: "activate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; addEventListener(type: "ariarequest", listener: (ev: AriaRequestEvent) => any, useCapture?: boolean): void; addEventListener(type: "beforeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; - addEventListener(type: "beforecopy", listener: (ev: DragEvent) => any, useCapture?: boolean): void; - addEventListener(type: "beforecut", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "beforecopy", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; + addEventListener(type: "beforecut", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "beforedeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; - addEventListener(type: "beforepaste", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "beforepaste", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void; addEventListener(type: "canplay", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "canplaythrough", listener: (ev: Event) => any, useCapture?: boolean): void; @@ -4373,9 +5011,9 @@ interface HTMLFrameElement extends HTMLElement, GetSVGDocument { addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "command", listener: (ev: CommandEvent) => any, useCapture?: boolean): void; addEventListener(type: "contextmenu", listener: (ev: PointerEvent) => any, useCapture?: boolean): void; - addEventListener(type: "copy", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "copy", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "cuechange", listener: (ev: Event) => any, useCapture?: boolean): void; - addEventListener(type: "cut", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "cut", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "deactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void; @@ -4387,11 +5025,12 @@ interface HTMLFrameElement extends HTMLElement, GetSVGDocument { addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void; addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void; - addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "ended", listener: (ev: MediaStreamErrorEvent) => any, useCapture?: boolean): void; addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void; addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void; addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void; addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "invalid", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; @@ -4408,8 +5047,8 @@ interface HTMLFrameElement extends HTMLElement, GetSVGDocument { addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; - addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void; - addEventListener(type: "paste", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "mousewheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void; + addEventListener(type: "paste", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void; @@ -4519,10 +5158,10 @@ interface HTMLFrameSetElement extends HTMLElement { addEventListener(type: "activate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; addEventListener(type: "ariarequest", listener: (ev: AriaRequestEvent) => any, useCapture?: boolean): void; addEventListener(type: "beforeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; - addEventListener(type: "beforecopy", listener: (ev: DragEvent) => any, useCapture?: boolean): void; - addEventListener(type: "beforecut", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "beforecopy", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; + addEventListener(type: "beforecut", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "beforedeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; - addEventListener(type: "beforepaste", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "beforepaste", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "beforeprint", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "beforeunload", listener: (ev: BeforeUnloadEvent) => any, useCapture?: boolean): void; addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void; @@ -4533,9 +5172,9 @@ interface HTMLFrameSetElement extends HTMLElement { addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "command", listener: (ev: CommandEvent) => any, useCapture?: boolean): void; addEventListener(type: "contextmenu", listener: (ev: PointerEvent) => any, useCapture?: boolean): void; - addEventListener(type: "copy", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "copy", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "cuechange", listener: (ev: Event) => any, useCapture?: boolean): void; - addEventListener(type: "cut", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "cut", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "deactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void; @@ -4547,7 +5186,7 @@ interface HTMLFrameSetElement extends HTMLElement { addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void; addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void; - addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "ended", listener: (ev: MediaStreamErrorEvent) => any, useCapture?: boolean): void; addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void; addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void; addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void; @@ -4555,6 +5194,7 @@ interface HTMLFrameSetElement extends HTMLElement { addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void; addEventListener(type: "hashchange", listener: (ev: HashChangeEvent) => any, useCapture?: boolean): void; addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "invalid", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; @@ -4572,13 +5212,13 @@ interface HTMLFrameSetElement extends HTMLElement { addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; - addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void; + addEventListener(type: "mousewheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void; addEventListener(type: "offline", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "online", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "orientationchange", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "pagehide", listener: (ev: PageTransitionEvent) => any, useCapture?: boolean): void; addEventListener(type: "pageshow", listener: (ev: PageTransitionEvent) => any, useCapture?: boolean): void; - addEventListener(type: "paste", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "paste", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void; @@ -4657,7 +5297,6 @@ interface HTMLHeadingElement extends HTMLElement { * Sets or retrieves a value that indicates the table alignment. */ align: string; - clear: string; } declare var HTMLHeadingElement: { @@ -4740,10 +5379,6 @@ interface HTMLIFrameElement extends HTMLElement, GetSVGDocument { * Sets or retrieves whether the frame can be scrolled. */ scrolling: string; - /** - * Sets the value indicating whether the source file of a frame or iframe has specific security restrictions applied. - */ - security: any; /** * Sets or retrieves a URL to be loaded by the object. */ @@ -4779,10 +5414,10 @@ interface HTMLIFrameElement extends HTMLElement, GetSVGDocument { addEventListener(type: "activate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; addEventListener(type: "ariarequest", listener: (ev: AriaRequestEvent) => any, useCapture?: boolean): void; addEventListener(type: "beforeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; - addEventListener(type: "beforecopy", listener: (ev: DragEvent) => any, useCapture?: boolean): void; - addEventListener(type: "beforecut", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "beforecopy", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; + addEventListener(type: "beforecut", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "beforedeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; - addEventListener(type: "beforepaste", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "beforepaste", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void; addEventListener(type: "canplay", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "canplaythrough", listener: (ev: Event) => any, useCapture?: boolean): void; @@ -4790,9 +5425,9 @@ interface HTMLIFrameElement extends HTMLElement, GetSVGDocument { addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "command", listener: (ev: CommandEvent) => any, useCapture?: boolean): void; addEventListener(type: "contextmenu", listener: (ev: PointerEvent) => any, useCapture?: boolean): void; - addEventListener(type: "copy", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "copy", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "cuechange", listener: (ev: Event) => any, useCapture?: boolean): void; - addEventListener(type: "cut", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "cut", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "deactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void; @@ -4804,11 +5439,12 @@ interface HTMLIFrameElement extends HTMLElement, GetSVGDocument { addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void; addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void; - addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "ended", listener: (ev: MediaStreamErrorEvent) => any, useCapture?: boolean): void; addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void; addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void; addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void; addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "invalid", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; @@ -4825,8 +5461,8 @@ interface HTMLIFrameElement extends HTMLElement, GetSVGDocument { addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; - addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void; - addEventListener(type: "paste", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "mousewheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void; + addEventListener(type: "paste", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void; @@ -4902,6 +5538,7 @@ interface HTMLImageElement extends HTMLElement { * Sets or retrieves a Uniform Resource Identifier (URI) to a long description of the object. */ longDesc: string; + lowsrc: string; /** * Gets or sets whether the DLNA PlayTo device is available. */ @@ -4927,6 +5564,7 @@ interface HTMLImageElement extends HTMLElement { * The original width of the image resource before sizing. */ naturalWidth: number; + sizes: string; /** * The address or URL of the a media resource that is to be considered. */ @@ -5071,6 +5709,7 @@ interface HTMLInputElement extends HTMLElement { * When present, marks an element that can't be submitted without a value. */ required: boolean; + selectionDirection: string; /** * Gets or sets the end position or offset of a text selection. */ @@ -5118,6 +5757,7 @@ interface HTMLInputElement extends HTMLElement { * Sets or retrieves the vertical margin for the object. */ vspace: number; + webkitdirectory: boolean; /** * Sets or retrieves the width of the object. */ @@ -5126,14 +5766,11 @@ interface HTMLInputElement extends HTMLElement { * Returns whether an element will successfully validate based on forms validation rules and constraints. */ willValidate: boolean; + minLength: number; /** * Returns whether a form will validate when it is submitted, without having to submit it. */ checkValidity(): boolean; - /** - * Creates a TextRange object for the element. - */ - createTextRange(): TextRange; /** * Makes the selection equal to the current object. */ @@ -5148,7 +5785,7 @@ interface HTMLInputElement extends HTMLElement { * @param start The offset into the text field for the start of the selection. * @param end The offset into the text field for the end of the selection. */ - setSelectionRange(start: number, end: number): void; + setSelectionRange(start?: number, end?: number, direction?: string): void; /** * Decrements a range input control's value by the value given by the Step attribute. If the optional parameter is used, it will decrement the input control's step value multiplied by the parameter's value. * @param n Value to decrement the value by. @@ -5166,23 +5803,6 @@ declare var HTMLInputElement: { new(): HTMLInputElement; } -interface HTMLIsIndexElement extends HTMLElement { - /** - * Sets or retrieves the URL to which the form content is sent for processing. - */ - action: string; - /** - * Retrieves a reference to the form that the object is embedded in. - */ - form: HTMLFormElement; - prompt: string; -} - -declare var HTMLIsIndexElement: { - prototype: HTMLIsIndexElement; - new(): HTMLIsIndexElement; -} - interface HTMLLIElement extends HTMLElement { type: string; /** @@ -5262,6 +5882,7 @@ interface HTMLLinkElement extends HTMLElement, LinkStyle { * Sets or retrieves the MIME type of the object. */ type: string; + import?: Document; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -5326,10 +5947,10 @@ interface HTMLMarqueeElement extends HTMLElement { addEventListener(type: "activate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; addEventListener(type: "ariarequest", listener: (ev: AriaRequestEvent) => any, useCapture?: boolean): void; addEventListener(type: "beforeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; - addEventListener(type: "beforecopy", listener: (ev: DragEvent) => any, useCapture?: boolean): void; - addEventListener(type: "beforecut", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "beforecopy", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; + addEventListener(type: "beforecut", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "beforedeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; - addEventListener(type: "beforepaste", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "beforepaste", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void; addEventListener(type: "bounce", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "canplay", listener: (ev: Event) => any, useCapture?: boolean): void; @@ -5338,9 +5959,9 @@ interface HTMLMarqueeElement extends HTMLElement { addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "command", listener: (ev: CommandEvent) => any, useCapture?: boolean): void; addEventListener(type: "contextmenu", listener: (ev: PointerEvent) => any, useCapture?: boolean): void; - addEventListener(type: "copy", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "copy", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "cuechange", listener: (ev: Event) => any, useCapture?: boolean): void; - addEventListener(type: "cut", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "cut", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "deactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void; @@ -5352,12 +5973,13 @@ interface HTMLMarqueeElement extends HTMLElement { addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void; addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void; - addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "ended", listener: (ev: MediaStreamErrorEvent) => any, useCapture?: boolean): void; addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void; addEventListener(type: "finish", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void; addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void; addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "invalid", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; @@ -5373,8 +5995,8 @@ interface HTMLMarqueeElement extends HTMLElement { addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; - addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void; - addEventListener(type: "paste", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "mousewheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void; + addEventListener(type: "paste", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void; @@ -5433,6 +6055,7 @@ interface HTMLMediaElement extends HTMLElement { * Gets or sets a flag that indicates whether the client provides a set of controls for the media (in case the developer does not include controls for the player). */ controls: boolean; + crossOrigin: string; /** * Gets the address or URL of the current media resource that is selected by IHTMLMediaElement. */ @@ -5462,6 +6085,7 @@ interface HTMLMediaElement extends HTMLElement { * Gets or sets a flag to specify whether playback should restart after it completes. */ loop: boolean; + mediaKeys: MediaKeys; /** * Specifies the purpose of the audio or video media, such as background audio or alerts. */ @@ -5503,6 +6127,7 @@ interface HTMLMediaElement extends HTMLElement { * Gets the current network activity for the element. */ networkState: number; + onencrypted: (ev: MediaEncryptedEvent) => any; onmsneedkey: (ev: MSMediaKeyNeededEvent) => any; /** * Gets a flag that specifies whether playback is paused. @@ -5533,6 +6158,7 @@ interface HTMLMediaElement extends HTMLElement { * The address or URL of the a media resource that is to be considered. */ src: string; + srcObject: MediaStream; textTracks: TextTrackList; videoTracks: VideoTrackList; /** @@ -5570,6 +6196,7 @@ interface HTMLMediaElement extends HTMLElement { * Loads and starts playback of a media resource. */ play(): void; + setMediaKeys(mediaKeys: MediaKeys): PromiseLike; HAVE_CURRENT_DATA: number; HAVE_ENOUGH_DATA: number; HAVE_FUTURE_DATA: number; @@ -5602,10 +6229,10 @@ interface HTMLMediaElement extends HTMLElement { addEventListener(type: "activate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; addEventListener(type: "ariarequest", listener: (ev: AriaRequestEvent) => any, useCapture?: boolean): void; addEventListener(type: "beforeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; - addEventListener(type: "beforecopy", listener: (ev: DragEvent) => any, useCapture?: boolean): void; - addEventListener(type: "beforecut", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "beforecopy", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; + addEventListener(type: "beforecut", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "beforedeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; - addEventListener(type: "beforepaste", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "beforepaste", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void; addEventListener(type: "canplay", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "canplaythrough", listener: (ev: Event) => any, useCapture?: boolean): void; @@ -5613,9 +6240,9 @@ interface HTMLMediaElement extends HTMLElement { addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "command", listener: (ev: CommandEvent) => any, useCapture?: boolean): void; addEventListener(type: "contextmenu", listener: (ev: PointerEvent) => any, useCapture?: boolean): void; - addEventListener(type: "copy", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "copy", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "cuechange", listener: (ev: Event) => any, useCapture?: boolean): void; - addEventListener(type: "cut", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "cut", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "deactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void; @@ -5627,11 +6254,13 @@ interface HTMLMediaElement extends HTMLElement { addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void; addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void; - addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "encrypted", listener: (ev: MediaEncryptedEvent) => any, useCapture?: boolean): void; + addEventListener(type: "ended", listener: (ev: MediaStreamErrorEvent) => any, useCapture?: boolean): void; addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void; addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void; addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void; addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "invalid", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; @@ -5647,9 +6276,9 @@ interface HTMLMediaElement extends HTMLElement { addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; - addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void; + addEventListener(type: "mousewheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void; addEventListener(type: "msneedkey", listener: (ev: MSMediaKeyNeededEvent) => any, useCapture?: boolean): void; - addEventListener(type: "paste", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "paste", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void; @@ -5741,6 +6370,20 @@ declare var HTMLMetaElement: { new(): HTMLMetaElement; } +interface HTMLMeterElement extends HTMLElement { + high: number; + low: number; + max: number; + min: number; + optimum: number; + value: number; +} + +declare var HTMLMeterElement: { + prototype: HTMLMeterElement; + new(): HTMLMeterElement; +} + interface HTMLModElement extends HTMLElement { /** * Sets or retrieves reference information about the object. @@ -5757,15 +6400,6 @@ declare var HTMLModElement: { new(): HTMLModElement; } -interface HTMLNextIdElement extends HTMLElement { - n: string; -} - -declare var HTMLNextIdElement: { - prototype: HTMLNextIdElement; - new(): HTMLNextIdElement; -} - interface HTMLOListElement extends HTMLElement { compact: boolean; /** @@ -5975,6 +6609,18 @@ declare var HTMLOptionElement: { create(): HTMLOptionElement; } +interface HTMLOptionsCollection extends HTMLCollection { + length: number; + selectedIndex: number; + add(element: HTMLOptionElement | HTMLOptGroupElement, before?: HTMLElement | number): void; + remove(index: number): void; +} + +declare var HTMLOptionsCollection: { + prototype: HTMLOptionsCollection; + new(): HTMLOptionsCollection; +} + interface HTMLParagraphElement extends HTMLElement { /** * Sets or retrieves how the object is aligned with adjacent text. @@ -6012,28 +6658,15 @@ declare var HTMLParamElement: { new(): HTMLParamElement; } -interface HTMLPhraseElement extends HTMLElement { - /** - * Sets or retrieves reference information about the object. - */ - cite: string; - /** - * Sets or retrieves the date and time of a modification to the object. - */ - dateTime: string; +interface HTMLPictureElement extends HTMLElement { } -declare var HTMLPhraseElement: { - prototype: HTMLPhraseElement; - new(): HTMLPhraseElement; +declare var HTMLPictureElement: { + prototype: HTMLPictureElement; + new(): HTMLPictureElement; } interface HTMLPreElement extends HTMLElement { - /** - * Indicates a citation by rendering text in italic type. - */ - cite: string; - clear: string; /** * Sets or gets a value that you can use to implement your own width functionality for the object. */ @@ -6074,10 +6707,6 @@ interface HTMLQuoteElement extends HTMLElement { * Sets or retrieves reference information about the object. */ cite: string; - /** - * Sets or retrieves the date and time of a modification to the object. - */ - dateTime: string; } declare var HTMLQuoteElement: { @@ -6153,6 +6782,7 @@ interface HTMLSelectElement extends HTMLElement { * Sets or retrieves the index of the selected option in a select object. */ selectedIndex: number; + selectedOptions: HTMLCollection; /** * Sets or retrieves the number of rows in the list box. */ @@ -6177,7 +6807,6 @@ interface HTMLSelectElement extends HTMLElement { * Returns whether an element will successfully validate based on forms validation rules and constraints. */ willValidate: boolean; - selectedOptions: HTMLCollection; /** * Adds an element to the areas, controlRange, or options collection. * @param element Variant of type Number that specifies the index position in the collection where the element is placed. If no value is given, the method places the element at the end of the collection. @@ -6223,10 +6852,12 @@ interface HTMLSourceElement extends HTMLElement { */ media: string; msKeySystem: string; + sizes: string; /** * The address or URL of the a media resource that is to be considered. */ src: string; + srcset: string; /** * Gets or sets the MIME type of a media resource. */ @@ -6247,6 +6878,7 @@ declare var HTMLSpanElement: { } interface HTMLStyleElement extends HTMLElement, LinkStyle { + disabled: boolean; /** * Sets or retrieves the media type. */ @@ -6552,6 +7184,15 @@ declare var HTMLTableSectionElement: { new(): HTMLTableSectionElement; } +interface HTMLTemplateElement extends HTMLElement { + content: DocumentFragment; +} + +declare var HTMLTemplateElement: { + prototype: HTMLTemplateElement; + new(): HTMLTemplateElement; +} + interface HTMLTextAreaElement extends HTMLElement { /** * Provides a way to direct a user to a specific field when a document loads. This can provide both direction and convenience for a user, reducing the need to click or tab to a field when a page opens. This attribute is true when present on an element, and false when missing. @@ -6630,14 +7271,11 @@ interface HTMLTextAreaElement extends HTMLElement { * Sets or retrieves how to handle wordwrapping in the object. */ wrap: string; + minLength: number; /** * Returns whether a form will validate when it is submitted, without having to submit it. */ checkValidity(): boolean; - /** - * Creates a TextRange object for the element. - */ - createTextRange(): TextRange; /** * Highlights the input area of a form element. */ @@ -6779,10 +7417,10 @@ interface HTMLVideoElement extends HTMLMediaElement { addEventListener(type: "activate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; addEventListener(type: "ariarequest", listener: (ev: AriaRequestEvent) => any, useCapture?: boolean): void; addEventListener(type: "beforeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; - addEventListener(type: "beforecopy", listener: (ev: DragEvent) => any, useCapture?: boolean): void; - addEventListener(type: "beforecut", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "beforecopy", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; + addEventListener(type: "beforecut", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "beforedeactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; - addEventListener(type: "beforepaste", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "beforepaste", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "blur", listener: (ev: FocusEvent) => any, useCapture?: boolean): void; addEventListener(type: "canplay", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "canplaythrough", listener: (ev: Event) => any, useCapture?: boolean): void; @@ -6790,9 +7428,9 @@ interface HTMLVideoElement extends HTMLMediaElement { addEventListener(type: "click", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "command", listener: (ev: CommandEvent) => any, useCapture?: boolean): void; addEventListener(type: "contextmenu", listener: (ev: PointerEvent) => any, useCapture?: boolean): void; - addEventListener(type: "copy", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "copy", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "cuechange", listener: (ev: Event) => any, useCapture?: boolean): void; - addEventListener(type: "cut", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "cut", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "deactivate", listener: (ev: UIEvent) => any, useCapture?: boolean): void; addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void; @@ -6804,11 +7442,13 @@ interface HTMLVideoElement extends HTMLMediaElement { addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void; addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void; - addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "encrypted", listener: (ev: MediaEncryptedEvent) => any, useCapture?: boolean): void; + addEventListener(type: "ended", listener: (ev: MediaStreamErrorEvent) => any, useCapture?: boolean): void; addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void; addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void; addEventListener(type: "gotpointercapture", listener: (ev: PointerEvent) => any, useCapture?: boolean): void; addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "invalid", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; @@ -6824,9 +7464,9 @@ interface HTMLVideoElement extends HTMLMediaElement { addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; - addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void; + addEventListener(type: "mousewheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void; addEventListener(type: "msneedkey", listener: (ev: MSMediaKeyNeededEvent) => any, useCapture?: boolean): void; - addEventListener(type: "paste", listener: (ev: DragEvent) => any, useCapture?: boolean): void; + addEventListener(type: "paste", listener: (ev: ClipboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "play", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "playing", listener: (ev: Event) => any, useCapture?: boolean): void; @@ -6894,11 +7534,11 @@ declare var History: { interface IDBCursor { direction: string; - key: any; + key: IDBKeyRange | IDBValidKey; primaryKey: any; source: IDBObjectStore | IDBIndex; advance(count: number): void; - continue(key?: any): void; + continue(key?: IDBKeyRange | IDBValidKey): void; delete(): IDBRequest; update(value: any): IDBRequest; NEXT: string; @@ -6931,10 +7571,12 @@ interface IDBDatabase extends EventTarget { onabort: (ev: Event) => any; onerror: (ev: Event) => any; version: number; + onversionchange: (ev: IDBVersionChangeEvent) => any; close(): void; createObjectStore(name: string, optionalParameters?: IDBObjectStoreParameters): IDBObjectStore; deleteObjectStore(name: string): void; transaction(storeNames: string | string[], mode?: string): IDBTransaction; + addEventListener(type: "versionchange", listener: (ev: IDBVersionChangeEvent) => any, useCapture?: boolean): void; addEventListener(type: "abort", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; @@ -6962,11 +7604,11 @@ interface IDBIndex { objectStore: IDBObjectStore; unique: boolean; multiEntry: boolean; - count(key?: any): IDBRequest; - get(key: any): IDBRequest; - getKey(key: any): IDBRequest; - openCursor(range?: IDBKeyRange, direction?: string): IDBRequest; - openKeyCursor(range?: IDBKeyRange, direction?: string): IDBRequest; + count(key?: IDBKeyRange | IDBValidKey): IDBRequest; + get(key: IDBKeyRange | IDBValidKey): IDBRequest; + getKey(key: IDBKeyRange | IDBValidKey): IDBRequest; + openCursor(range?: IDBKeyRange | IDBValidKey, direction?: string): IDBRequest; + openKeyCursor(range?: IDBKeyRange | IDBValidKey, direction?: string): IDBRequest; } declare var IDBIndex: { @@ -6985,9 +7627,9 @@ declare var IDBKeyRange: { prototype: IDBKeyRange; new(): IDBKeyRange; bound(lower: any, upper: any, lowerOpen?: boolean, upperOpen?: boolean): IDBKeyRange; - lowerBound(bound: any, open?: boolean): IDBKeyRange; + lowerBound(lower: any, open?: boolean): IDBKeyRange; only(value: any): IDBKeyRange; - upperBound(bound: any, open?: boolean): IDBKeyRange; + upperBound(upper: any, open?: boolean): IDBKeyRange; } interface IDBObjectStore { @@ -6996,16 +7638,16 @@ interface IDBObjectStore { name: string; transaction: IDBTransaction; autoIncrement: boolean; - add(value: any, key?: any): IDBRequest; + add(value: any, key?: IDBKeyRange | IDBValidKey): IDBRequest; clear(): IDBRequest; - count(key?: any): IDBRequest; + count(key?: IDBKeyRange | IDBValidKey): IDBRequest; createIndex(name: string, keyPath: string | string[], optionalParameters?: IDBIndexParameters): IDBIndex; - delete(key: any): IDBRequest; + delete(key: IDBKeyRange | IDBValidKey): IDBRequest; deleteIndex(indexName: string): void; get(key: any): IDBRequest; index(name: string): IDBIndex; - openCursor(range?: any, direction?: string): IDBRequest; - put(value: any, key?: any): IDBRequest; + openCursor(range?: IDBKeyRange | IDBValidKey, direction?: string): IDBRequest; + put(value: any, key?: IDBKeyRange | IDBValidKey): IDBRequest; } declare var IDBObjectStore: { @@ -7128,6 +7770,16 @@ declare var KeyboardEvent: { DOM_KEY_LOCATION_STANDARD: number; } +interface ListeningStateChangedEvent extends Event { + label: string; + state: string; +} + +declare var ListeningStateChangedEvent: { + prototype: ListeningStateChangedEvent; + new(): ListeningStateChangedEvent; +} + interface Location { hash: string; host: string; @@ -7169,7 +7821,7 @@ interface MSApp { execAsyncAtPriority(asynchronousCallback: MSExecAtPriorityFunctionCallback, priority: string, ...args: any[]): void; execAtPriority(synchronousCallback: MSExecAtPriorityFunctionCallback, priority: string, ...args: any[]): any; getCurrentPriority(): string; - getHtmlPrintDocumentSourceAsync(htmlDoc: any): any; + getHtmlPrintDocumentSourceAsync(htmlDoc: any): PromiseLike; getViewId(view: any): any; isTaskScheduledAtPriorityOrHigher(priority: string): boolean; pageHandlesAllApplicationActivations(enabled: boolean): void; @@ -7205,6 +7857,16 @@ declare var MSAppAsyncOperation: { STARTED: number; } +interface MSAssertion { + id: string; + type: string; +} + +declare var MSAssertion: { + prototype: MSAssertion; + new(): MSAssertion; +} + interface MSBlobBuilder { append(data: any, endings?: string): void; getBlob(contentType?: string): Blob; @@ -7215,44 +7877,46 @@ declare var MSBlobBuilder: { new(): MSBlobBuilder; } -interface MSCSSMatrix { - a: number; - b: number; - c: number; - d: number; - e: number; - f: number; - m11: number; - m12: number; - m13: number; - m14: number; - m21: number; - m22: number; - m23: number; - m24: number; - m31: number; - m32: number; - m33: number; - m34: number; - m41: number; - m42: number; - m43: number; - m44: number; - inverse(): MSCSSMatrix; - multiply(secondMatrix: MSCSSMatrix): MSCSSMatrix; - rotate(angleX: number, angleY?: number, angleZ?: number): MSCSSMatrix; - rotateAxisAngle(x: number, y: number, z: number, angle: number): MSCSSMatrix; - scale(scaleX: number, scaleY?: number, scaleZ?: number): MSCSSMatrix; - setMatrixValue(value: string): void; - skewX(angle: number): MSCSSMatrix; - skewY(angle: number): MSCSSMatrix; - toString(): string; - translate(x: number, y: number, z?: number): MSCSSMatrix; +interface MSCredentials { + getAssertion(challenge: string, filter?: MSCredentialFilter, params?: MSSignatureParameters): PromiseLike; + makeCredential(accountInfo: MSAccountInfo, params: MSCredentialParameters[], challenge?: string): PromiseLike; } -declare var MSCSSMatrix: { - prototype: MSCSSMatrix; - new(text?: string): MSCSSMatrix; +declare var MSCredentials: { + prototype: MSCredentials; + new(): MSCredentials; +} + +interface MSFIDOCredentialAssertion extends MSAssertion { + algorithm: string | Algorithm; + attestation: any; + publicKey: string; + transportHints: string[]; +} + +declare var MSFIDOCredentialAssertion: { + prototype: MSFIDOCredentialAssertion; + new(): MSFIDOCredentialAssertion; +} + +interface MSFIDOSignature { + authnrData: string; + clientData: string; + signature: string; +} + +declare var MSFIDOSignature: { + prototype: MSFIDOSignature; + new(): MSFIDOSignature; +} + +interface MSFIDOSignatureAssertion extends MSAssertion { + signature: MSFIDOSignature; +} + +declare var MSFIDOSignatureAssertion: { + prototype: MSFIDOSignatureAssertion; + new(): MSFIDOSignatureAssertion; } interface MSGesture { @@ -7457,25 +8121,7 @@ declare var MSMediaKeys: { prototype: MSMediaKeys; new(keySystem: string): MSMediaKeys; isTypeSupported(keySystem: string, type?: string): boolean; -} - -interface MSMimeTypesCollection { - length: number; -} - -declare var MSMimeTypesCollection: { - prototype: MSMimeTypesCollection; - new(): MSMimeTypesCollection; -} - -interface MSPluginsCollection { - length: number; - refresh(reload?: boolean): void; -} - -declare var MSPluginsCollection: { - prototype: MSPluginsCollection; - new(): MSPluginsCollection; + isTypeSupportedWithFeatures(keySystem: string, type?: string): string; } interface MSPointerEvent extends MouseEvent { @@ -7589,6 +8235,32 @@ declare var MSWebViewSettings: { new(): MSWebViewSettings; } +interface MediaDeviceInfo { + deviceId: string; + groupId: string; + kind: string; + label: string; +} + +declare var MediaDeviceInfo: { + prototype: MediaDeviceInfo; + new(): MediaDeviceInfo; +} + +interface MediaDevices extends EventTarget { + ondevicechange: (ev: Event) => any; + enumerateDevices(): any; + getSupportedConstraints(): MediaTrackSupportedConstraints; + getUserMedia(constraints: MediaStreamConstraints): PromiseLike; + addEventListener(type: "devicechange", listener: (ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +} + +declare var MediaDevices: { + prototype: MediaDevices; + new(): MediaDevices; +} + interface MediaElementAudioSourceNode extends AudioNode { } @@ -7597,6 +8269,16 @@ declare var MediaElementAudioSourceNode: { new(): MediaElementAudioSourceNode; } +interface MediaEncryptedEvent extends Event { + initData: ArrayBuffer; + initDataType: string; +} + +declare var MediaEncryptedEvent: { + prototype: MediaEncryptedEvent; + new(type: string, eventInitDict?: MediaEncryptedEventInit): MediaEncryptedEvent; +} + interface MediaError { code: number; msExtendedCode: number; @@ -7617,6 +8299,66 @@ declare var MediaError: { MS_MEDIA_ERR_ENCRYPTED: number; } +interface MediaKeyMessageEvent extends Event { + message: ArrayBuffer; + messageType: string; +} + +declare var MediaKeyMessageEvent: { + prototype: MediaKeyMessageEvent; + new(type: string, eventInitDict?: MediaKeyMessageEventInit): MediaKeyMessageEvent; +} + +interface MediaKeySession extends EventTarget { + closed: PromiseLike; + expiration: number; + keyStatuses: MediaKeyStatusMap; + sessionId: string; + close(): PromiseLike; + generateRequest(initDataType: string, initData: any): PromiseLike; + load(sessionId: string): PromiseLike; + remove(): PromiseLike; + update(response: any): PromiseLike; +} + +declare var MediaKeySession: { + prototype: MediaKeySession; + new(): MediaKeySession; +} + +interface MediaKeyStatusMap { + size: number; + forEach(callback: ForEachCallback): void; + get(keyId: any): string; + has(keyId: any): boolean; +} + +declare var MediaKeyStatusMap: { + prototype: MediaKeyStatusMap; + new(): MediaKeyStatusMap; +} + +interface MediaKeySystemAccess { + keySystem: string; + createMediaKeys(): PromiseLike; + getConfiguration(): MediaKeySystemConfiguration; +} + +declare var MediaKeySystemAccess: { + prototype: MediaKeySystemAccess; + new(): MediaKeySystemAccess; +} + +interface MediaKeys { + createSession(sessionType?: string): MediaKeySession; + setServerCertificate(serverCertificate: any): PromiseLike; +} + +declare var MediaKeys: { + prototype: MediaKeys; + new(): MediaKeys; +} + interface MediaList { length: number; mediaText: string; @@ -7660,6 +8402,101 @@ declare var MediaSource: { isTypeSupported(type: string): boolean; } +interface MediaStream extends EventTarget { + active: boolean; + id: string; + onactive: (ev: Event) => any; + onaddtrack: (ev: TrackEvent) => any; + oninactive: (ev: Event) => any; + onremovetrack: (ev: TrackEvent) => any; + addTrack(track: MediaStreamTrack): void; + clone(): MediaStream; + getAudioTracks(): MediaStreamTrack[]; + getTrackById(trackId: string): MediaStreamTrack; + getTracks(): MediaStreamTrack[]; + getVideoTracks(): MediaStreamTrack[]; + removeTrack(track: MediaStreamTrack): void; + stop(): void; + addEventListener(type: "active", listener: (ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "addtrack", listener: (ev: TrackEvent) => any, useCapture?: boolean): void; + addEventListener(type: "inactive", listener: (ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "removetrack", listener: (ev: TrackEvent) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +} + +declare var MediaStream: { + prototype: MediaStream; + new(streamOrTracks?: MediaStream | MediaStreamTrack[]): MediaStream; +} + +interface MediaStreamAudioSourceNode extends AudioNode { +} + +declare var MediaStreamAudioSourceNode: { + prototype: MediaStreamAudioSourceNode; + new(): MediaStreamAudioSourceNode; +} + +interface MediaStreamError { + constraintName: string; + message: string; + name: string; +} + +declare var MediaStreamError: { + prototype: MediaStreamError; + new(): MediaStreamError; +} + +interface MediaStreamErrorEvent extends Event { + error: MediaStreamError; +} + +declare var MediaStreamErrorEvent: { + prototype: MediaStreamErrorEvent; + new(type: string, eventInitDict?: MediaStreamErrorEventInit): MediaStreamErrorEvent; +} + +interface MediaStreamTrack extends EventTarget { + enabled: boolean; + id: string; + kind: string; + label: string; + muted: boolean; + onended: (ev: MediaStreamErrorEvent) => any; + onmute: (ev: Event) => any; + onoverconstrained: (ev: MediaStreamErrorEvent) => any; + onunmute: (ev: Event) => any; + readonly: boolean; + readyState: string; + remote: boolean; + applyConstraints(constraints: MediaTrackConstraints): PromiseLike; + clone(): MediaStreamTrack; + getCapabilities(): MediaTrackCapabilities; + getConstraints(): MediaTrackConstraints; + getSettings(): MediaTrackSettings; + stop(): void; + addEventListener(type: "ended", listener: (ev: MediaStreamErrorEvent) => any, useCapture?: boolean): void; + addEventListener(type: "mute", listener: (ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "overconstrained", listener: (ev: MediaStreamErrorEvent) => any, useCapture?: boolean): void; + addEventListener(type: "unmute", listener: (ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +} + +declare var MediaStreamTrack: { + prototype: MediaStreamTrack; + new(): MediaStreamTrack; +} + +interface MediaStreamTrackEvent extends Event { + track: MediaStreamTrack; +} + +declare var MediaStreamTrackEvent: { + prototype: MediaStreamTrackEvent; + new(type: string, eventInitDict?: MediaStreamTrackEventInit): MediaStreamTrackEvent; +} + interface MessageChannel { port1: MessagePort; port2: MessagePort; @@ -7755,18 +8592,6 @@ declare var MouseEvent: { new(typeArg: string, eventInitDict?: MouseEventInit): MouseEvent; } -interface MouseWheelEvent extends MouseEvent { - wheelDelta: number; - wheelDeltaX: number; - wheelDeltaY: number; - initMouseWheelEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, buttonArg: number, relatedTargetArg: EventTarget, modifiersListArg: string, wheelDeltaArg: number): void; -} - -declare var MouseWheelEvent: { - prototype: MouseWheelEvent; - new(): MouseWheelEvent; -} - interface MutationEvent extends Event { attrChange: number; attrName: string; @@ -7860,27 +8685,22 @@ declare var NavigationEventWithReferrer: { new(): NavigationEventWithReferrer; } -interface Navigator extends Object, NavigatorID, NavigatorOnLine, NavigatorContentUtils, NavigatorStorageUtils, NavigatorGeolocation, MSNavigatorDoNotTrack, MSFileSaver { +interface Navigator extends Object, NavigatorID, NavigatorOnLine, NavigatorContentUtils, NavigatorStorageUtils, NavigatorGeolocation, MSNavigatorDoNotTrack, MSFileSaver, NavigatorUserMedia { appCodeName: string; - appMinorVersion: string; - browserLanguage: string; - connectionSpeed: number; cookieEnabled: boolean; - cpuClass: string; language: string; maxTouchPoints: number; - mimeTypes: MSMimeTypesCollection; + mimeTypes: MimeTypeArray; msManipulationViewsEnabled: boolean; msMaxTouchPoints: number; msPointerEnabled: boolean; - plugins: MSPluginsCollection; + plugins: PluginArray; pointerEnabled: boolean; - systemLanguage: string; - userLanguage: string; webdriver: boolean; getGamepads(): Gamepad[]; javaEnabled(): boolean; msLaunchUri(uri: string, successCallback?: MSLaunchUriCallback, noHandlerCallback?: MSLaunchUriCallback): void; + requestMediaKeySystemAccess(keySystem: string, supportedConfigurations: MediaKeySystemConfiguration[]): PromiseLike; vibrate(pattern: number | number[]): boolean; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -7905,12 +8725,12 @@ interface Node extends EventTarget { ownerDocument: Document; parentElement: HTMLElement; parentNode: Node; - prefix: string; previousSibling: Node; textContent: string; appendChild(newChild: Node): Node; cloneNode(deep?: boolean): Node; compareDocumentPosition(other: Node): number; + contains(child: Node): boolean; hasAttributes(): boolean; hasChildNodes(): boolean; insertBefore(newChild: Node, refChild?: Node): Node; @@ -8060,7 +8880,7 @@ declare var OfflineAudioCompletionEvent: { interface OfflineAudioContext extends AudioContext { oncomplete: (ev: Event) => any; - startRendering(): void; + startRendering(): PromiseLike; addEventListener(type: "complete", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -8073,12 +8893,12 @@ declare var OfflineAudioContext: { interface OscillatorNode extends AudioNode { detune: AudioParam; frequency: AudioParam; - onended: (ev: Event) => any; + onended: (ev: MediaStreamErrorEvent) => any; type: string; setPeriodicWave(periodicWave: PeriodicWave): void; start(when?: number): void; stop(when?: number): void; - addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "ended", listener: (ev: MediaStreamErrorEvent) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -8087,6 +8907,23 @@ declare var OscillatorNode: { new(): OscillatorNode; } +interface OverflowEvent extends UIEvent { + horizontalOverflow: boolean; + orient: number; + verticalOverflow: boolean; + BOTH: number; + HORIZONTAL: number; + VERTICAL: number; +} + +declare var OverflowEvent: { + prototype: OverflowEvent; + new(): OverflowEvent; + BOTH: number; + HORIZONTAL: number; + VERTICAL: number; +} + interface PageTransitionEvent extends Event { persisted: boolean; } @@ -8430,6 +9267,203 @@ declare var ProgressEvent: { new(type: string, eventInitDict?: ProgressEventInit): ProgressEvent; } +interface RTCDTMFToneChangeEvent extends Event { + tone: string; +} + +declare var RTCDTMFToneChangeEvent: { + prototype: RTCDTMFToneChangeEvent; + new(type: string, eventInitDict: RTCDTMFToneChangeEventInit): RTCDTMFToneChangeEvent; +} + +interface RTCDtlsTransport extends RTCStatsProvider { + ondtlsstatechange: (ev: RTCDtlsTransportStateChangedEvent) => any; + onerror: (ev: Event) => any; + state: string; + transport: RTCIceTransport; + getLocalParameters(): RTCDtlsParameters; + getRemoteCertificates(): ArrayBuffer[]; + getRemoteParameters(): RTCDtlsParameters; + start(remoteParameters: RTCDtlsParameters): void; + stop(): void; + addEventListener(type: "dtlsstatechange", listener: (ev: RTCDtlsTransportStateChangedEvent) => any, useCapture?: boolean): void; + addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +} + +declare var RTCDtlsTransport: { + prototype: RTCDtlsTransport; + new(transport: RTCIceTransport): RTCDtlsTransport; +} + +interface RTCDtlsTransportStateChangedEvent extends Event { + state: string; +} + +declare var RTCDtlsTransportStateChangedEvent: { + prototype: RTCDtlsTransportStateChangedEvent; + new(): RTCDtlsTransportStateChangedEvent; +} + +interface RTCDtmfSender extends EventTarget { + canInsertDTMF: boolean; + duration: number; + interToneGap: number; + ontonechange: (ev: RTCDTMFToneChangeEvent) => any; + sender: RTCRtpSender; + toneBuffer: string; + insertDTMF(tones: string, duration?: number, interToneGap?: number): void; + addEventListener(type: "tonechange", listener: (ev: RTCDTMFToneChangeEvent) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +} + +declare var RTCDtmfSender: { + prototype: RTCDtmfSender; + new(sender: RTCRtpSender): RTCDtmfSender; +} + +interface RTCIceCandidatePairChangedEvent extends Event { + pair: RTCIceCandidatePair; +} + +declare var RTCIceCandidatePairChangedEvent: { + prototype: RTCIceCandidatePairChangedEvent; + new(): RTCIceCandidatePairChangedEvent; +} + +interface RTCIceGatherer extends RTCStatsProvider { + component: string; + onerror: (ev: Event) => any; + onlocalcandidate: (ev: RTCIceGathererEvent) => any; + createAssociatedGatherer(): RTCIceGatherer; + getLocalCandidates(): RTCIceCandidate[]; + getLocalParameters(): RTCIceParameters; + addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void; + addEventListener(type: "localcandidate", listener: (ev: RTCIceGathererEvent) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +} + +declare var RTCIceGatherer: { + prototype: RTCIceGatherer; + new(options: RTCIceGatherOptions): RTCIceGatherer; +} + +interface RTCIceGathererEvent extends Event { + candidate: RTCIceCandidate | RTCIceCandidateComplete; +} + +declare var RTCIceGathererEvent: { + prototype: RTCIceGathererEvent; + new(): RTCIceGathererEvent; +} + +interface RTCIceTransport extends RTCStatsProvider { + component: string; + iceGatherer: RTCIceGatherer; + oncandidatepairchange: (ev: RTCIceCandidatePairChangedEvent) => any; + onicestatechange: (ev: RTCIceTransportStateChangedEvent) => any; + role: string; + state: string; + addRemoteCandidate(remoteCandidate: RTCIceCandidate | RTCIceCandidateComplete): void; + createAssociatedTransport(): RTCIceTransport; + getNominatedCandidatePair(): RTCIceCandidatePair; + getRemoteCandidates(): RTCIceCandidate[]; + getRemoteParameters(): RTCIceParameters; + setRemoteCandidates(remoteCandidates: RTCIceCandidate[]): void; + start(gatherer: RTCIceGatherer, remoteParameters: RTCIceParameters, role?: string): void; + stop(): void; + addEventListener(type: "candidatepairchange", listener: (ev: RTCIceCandidatePairChangedEvent) => any, useCapture?: boolean): void; + addEventListener(type: "icestatechange", listener: (ev: RTCIceTransportStateChangedEvent) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +} + +declare var RTCIceTransport: { + prototype: RTCIceTransport; + new(): RTCIceTransport; +} + +interface RTCIceTransportStateChangedEvent extends Event { + state: string; +} + +declare var RTCIceTransportStateChangedEvent: { + prototype: RTCIceTransportStateChangedEvent; + new(): RTCIceTransportStateChangedEvent; +} + +interface RTCRtpReceiver extends RTCStatsProvider { + onerror: (ev: Event) => any; + rtcpTransport: RTCDtlsTransport; + track: MediaStreamTrack; + transport: RTCDtlsTransport | RTCSrtpSdesTransport; + getContributingSources(): RTCRtpContributingSource[]; + receive(parameters: RTCRtpParameters): void; + requestSendCSRC(csrc: number): void; + setTransport(transport: RTCDtlsTransport | RTCSrtpSdesTransport, rtcpTransport?: RTCDtlsTransport): void; + stop(): void; + addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +} + +declare var RTCRtpReceiver: { + prototype: RTCRtpReceiver; + new(transport: RTCDtlsTransport | RTCSrtpSdesTransport, kind: string, rtcpTransport?: RTCDtlsTransport): RTCRtpReceiver; + getCapabilities(kind?: string): RTCRtpCapabilities; +} + +interface RTCRtpSender extends RTCStatsProvider { + onerror: (ev: Event) => any; + onssrcconflict: (ev: RTCSsrcConflictEvent) => any; + rtcpTransport: RTCDtlsTransport; + track: MediaStreamTrack; + transport: RTCDtlsTransport | RTCSrtpSdesTransport; + send(parameters: RTCRtpParameters): void; + setTrack(track: MediaStreamTrack): void; + setTransport(transport: RTCDtlsTransport | RTCSrtpSdesTransport, rtcpTransport?: RTCDtlsTransport): void; + stop(): void; + addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void; + addEventListener(type: "ssrcconflict", listener: (ev: RTCSsrcConflictEvent) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +} + +declare var RTCRtpSender: { + prototype: RTCRtpSender; + new(track: MediaStreamTrack, transport: RTCDtlsTransport | RTCSrtpSdesTransport, rtcpTransport?: RTCDtlsTransport): RTCRtpSender; + getCapabilities(kind?: string): RTCRtpCapabilities; +} + +interface RTCSrtpSdesTransport extends EventTarget { + onerror: (ev: Event) => any; + transport: RTCIceTransport; + addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +} + +declare var RTCSrtpSdesTransport: { + prototype: RTCSrtpSdesTransport; + new(transport: RTCIceTransport, encryptParameters: RTCSrtpSdesParameters, decryptParameters: RTCSrtpSdesParameters): RTCSrtpSdesTransport; + getLocalParameters(): RTCSrtpSdesParameters[]; +} + +interface RTCSsrcConflictEvent extends Event { + ssrc: number; +} + +declare var RTCSsrcConflictEvent: { + prototype: RTCSsrcConflictEvent; + new(): RTCSsrcConflictEvent; +} + +interface RTCStatsProvider extends EventTarget { + getStats(): PromiseLike; + msGetStats(): PromiseLike; +} + +declare var RTCStatsProvider: { + prototype: RTCStatsProvider; + new(): RTCStatsProvider; +} + interface Range { collapsed: boolean; commonAncestorContainer: Node; @@ -8696,7 +9730,6 @@ declare var SVGDescElement: { } interface SVGElement extends Element { - id: string; onclick: (ev: MouseEvent) => any; ondblclick: (ev: MouseEvent) => any; onfocusin: (ev: FocusEvent) => any; @@ -10021,6 +11054,7 @@ declare var SVGStringList: { } interface SVGStyleElement extends SVGElement, SVGLangSpace { + disabled: boolean; media: string; title: string; type: string; @@ -10365,7 +11399,7 @@ declare var StereoPannerNode: { interface Storage { length: number; clear(): void; - getItem(key: string): any; + getItem(key: string): string; key(index: number): string; removeItem(key: string): void; setItem(key: string, data: string): void; @@ -10439,18 +11473,18 @@ declare var StyleSheetPageList: { } interface SubtleCrypto { - decrypt(algorithm: string | Algorithm, key: CryptoKey, data: ArrayBufferView): any; - deriveBits(algorithm: string | Algorithm, baseKey: CryptoKey, length: number): any; - deriveKey(algorithm: string | Algorithm, baseKey: CryptoKey, derivedKeyType: string | Algorithm, extractable: boolean, keyUsages: string[]): any; - digest(algorithm: string | Algorithm, data: ArrayBufferView): any; - encrypt(algorithm: string | Algorithm, key: CryptoKey, data: ArrayBufferView): any; - exportKey(format: string, key: CryptoKey): any; - generateKey(algorithm: string | Algorithm, extractable: boolean, keyUsages: string[]): any; - importKey(format: string, keyData: ArrayBufferView, algorithm: string | Algorithm, extractable: boolean, keyUsages: string[]): any; - sign(algorithm: string | Algorithm, key: CryptoKey, data: ArrayBufferView): any; - unwrapKey(format: string, wrappedKey: ArrayBufferView, unwrappingKey: CryptoKey, unwrapAlgorithm: string | Algorithm, unwrappedKeyAlgorithm: string | Algorithm, extractable: boolean, keyUsages: string[]): any; - verify(algorithm: string | Algorithm, key: CryptoKey, signature: ArrayBufferView, data: ArrayBufferView): any; - wrapKey(format: string, key: CryptoKey, wrappingKey: CryptoKey, wrapAlgorithm: string | Algorithm): any; + decrypt(algorithm: string | Algorithm, key: CryptoKey, data: ArrayBufferView): PromiseLike; + deriveBits(algorithm: string | Algorithm, baseKey: CryptoKey, length: number): PromiseLike; + deriveKey(algorithm: string | Algorithm, baseKey: CryptoKey, derivedKeyType: string | Algorithm, extractable: boolean, keyUsages: string[]): PromiseLike; + digest(algorithm: string | Algorithm, data: ArrayBufferView): PromiseLike; + encrypt(algorithm: string | Algorithm, key: CryptoKey, data: ArrayBufferView): PromiseLike; + exportKey(format: string, key: CryptoKey): PromiseLike; + generateKey(algorithm: string | Algorithm, extractable: boolean, keyUsages: string[]): PromiseLike; + importKey(format: string, keyData: ArrayBufferView, algorithm: string | Algorithm, extractable: boolean, keyUsages: string[]): PromiseLike; + sign(algorithm: string | Algorithm, key: CryptoKey, data: ArrayBufferView): PromiseLike; + unwrapKey(format: string, wrappedKey: ArrayBufferView, unwrappingKey: CryptoKey, unwrapAlgorithm: string | Algorithm, unwrappedKeyAlgorithm: string | Algorithm, extractable: boolean, keyUsages: string[]): PromiseLike; + verify(algorithm: string | Algorithm, key: CryptoKey, signature: ArrayBufferView, data: ArrayBufferView): PromiseLike; + wrapKey(format: string, key: CryptoKey, wrappingKey: CryptoKey, wrapAlgorithm: string | Algorithm): PromiseLike; } declare var SubtleCrypto: { @@ -10460,7 +11494,6 @@ declare var SubtleCrypto: { interface Text extends CharacterData { wholeText: string; - replaceWholeText(content: string): Text; splitText(offset: number): Text; } @@ -10510,62 +11543,6 @@ declare var TextMetrics: { new(): TextMetrics; } -interface TextRange { - boundingHeight: number; - boundingLeft: number; - boundingTop: number; - boundingWidth: number; - htmlText: string; - offsetLeft: number; - offsetTop: number; - text: string; - collapse(start?: boolean): void; - compareEndPoints(how: string, sourceRange: TextRange): number; - duplicate(): TextRange; - execCommand(cmdID: string, showUI?: boolean, value?: any): boolean; - execCommandShowHelp(cmdID: string): boolean; - expand(Unit: string): boolean; - findText(string: string, count?: number, flags?: number): boolean; - getBookmark(): string; - getBoundingClientRect(): ClientRect; - getClientRects(): ClientRectList; - inRange(range: TextRange): boolean; - isEqual(range: TextRange): boolean; - move(unit: string, count?: number): number; - moveEnd(unit: string, count?: number): number; - moveStart(unit: string, count?: number): number; - moveToBookmark(bookmark: string): boolean; - moveToElementText(element: Element): void; - moveToPoint(x: number, y: number): void; - parentElement(): Element; - pasteHTML(html: string): void; - queryCommandEnabled(cmdID: string): boolean; - queryCommandIndeterm(cmdID: string): boolean; - queryCommandState(cmdID: string): boolean; - queryCommandSupported(cmdID: string): boolean; - queryCommandText(cmdID: string): string; - queryCommandValue(cmdID: string): any; - scrollIntoView(fStart?: boolean): void; - select(): void; - setEndPoint(how: string, SourceRange: TextRange): void; -} - -declare var TextRange: { - prototype: TextRange; - new(): TextRange; -} - -interface TextRangeCollection { - length: number; - item(index: number): TextRange; - [index: number]: TextRange; -} - -declare var TextRangeCollection: { - prototype: TextRangeCollection; - new(): TextRangeCollection; -} - interface TextTrack extends EventTarget { activeCues: TextTrackCueList; cues: TextTrackCueList; @@ -10756,10 +11733,26 @@ declare var UIEvent: { } interface URL { + hash: string; + host: string; + hostname: string; + href: string; + origin: string; + password: string; + pathname: string; + port: string; + protocol: string; + search: string; + username: string; + toString(): string; +} + +declare var URL: { + prototype: URL; + new(url: string, base?: string): URL; createObjectURL(object: any, options?: ObjectURLOptions): string; revokeObjectURL(url: string): void; } -declare var URL: URL; interface UnviewableContentIdentifiedEvent extends NavigationEventWithReferrer { mediaType: string; @@ -10908,7 +11901,7 @@ interface WebGLContextEvent extends Event { declare var WebGLContextEvent: { prototype: WebGLContextEvent; - new(): WebGLContextEvent; + new(type: string, eventInitDict?: WebGLContextEventInit): WebGLContextEvent; } interface WebGLFramebuffer extends WebGLObject { @@ -11815,6 +12808,9 @@ interface WheelEvent extends MouseEvent { deltaX: number; deltaY: number; deltaZ: number; + wheelDelta: number; + wheelDeltaX: number; + wheelDeltaY: number; getCurrentPoint(element: Element): void; initWheelEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, buttonArg: number, relatedTargetArg: EventTarget, modifiersListArg: string, deltaXArg: number, deltaYArg: number, deltaZArg: number, deltaMode: number): void; DOM_DELTA_LINE: number; @@ -11831,7 +12827,6 @@ declare var WheelEvent: { } interface Window extends EventTarget, WindowTimers, WindowSessionStorage, WindowLocalStorage, WindowConsole, GlobalEventHandlers, IDBEnvironment, WindowBase64 { - animationStartTime: number; applicationCache: ApplicationCache; clientInformation: Navigator; closed: boolean; @@ -11851,7 +12846,7 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window location: Location; locationbar: BarProp; menubar: BarProp; - msAnimationStartTime: number; + msCredentials: MSCredentials; name: string; navigator: Navigator; offscreenBuffering: string | boolean; @@ -11867,6 +12862,7 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window oncompassneedscalibration: (ev: Event) => any; oncontextmenu: (ev: PointerEvent) => any; ondblclick: (ev: MouseEvent) => any; + ondevicelight: (ev: DeviceLightEvent) => any; ondevicemotion: (ev: DeviceMotionEvent) => any; ondeviceorientation: (ev: DeviceOrientationEvent) => any; ondrag: (ev: DragEvent) => any; @@ -11878,11 +12874,12 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window ondrop: (ev: DragEvent) => any; ondurationchange: (ev: Event) => any; onemptied: (ev: Event) => any; - onended: (ev: Event) => any; + onended: (ev: MediaStreamErrorEvent) => any; onerror: ErrorEventHandler; onfocus: (ev: FocusEvent) => any; onhashchange: (ev: HashChangeEvent) => any; oninput: (ev: Event) => any; + oninvalid: (ev: Event) => any; onkeydown: (ev: KeyboardEvent) => any; onkeypress: (ev: KeyboardEvent) => any; onkeyup: (ev: KeyboardEvent) => any; @@ -11898,7 +12895,7 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window onmouseout: (ev: MouseEvent) => any; onmouseover: (ev: MouseEvent) => any; onmouseup: (ev: MouseEvent) => any; - onmousewheel: (ev: MouseWheelEvent) => any; + onmousewheel: (ev: WheelEvent) => any; onmsgesturechange: (ev: MSGestureEvent) => any; onmsgesturedoubletap: (ev: MSGestureEvent) => any; onmsgestureend: (ev: MSGestureEvent) => any; @@ -11937,10 +12934,10 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window onsubmit: (ev: Event) => any; onsuspend: (ev: Event) => any; ontimeupdate: (ev: Event) => any; - ontouchcancel: any; - ontouchend: any; - ontouchmove: any; - ontouchstart: any; + ontouchcancel: (ev: TouchEvent) => any; + ontouchend: (ev: TouchEvent) => any; + ontouchmove: (ev: TouchEvent) => any; + ontouchstart: (ev: TouchEvent) => any; onunload: (ev: Event) => any; onvolumechange: (ev: Event) => any; onwaiting: (ev: Event) => any; @@ -11968,7 +12965,7 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window toolbar: BarProp; top: Window; window: Window; - URL: URL; + URL: typeof URL; alert(message?: any): void; blur(): void; cancelAnimationFrame(handle: number): void; @@ -11982,12 +12979,9 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window matchMedia(mediaQuery: string): MediaQueryList; moveBy(x?: number, y?: number): void; moveTo(x?: number, y?: number): void; - msCancelRequestAnimationFrame(handle: number): void; - msMatchMedia(mediaQuery: string): MediaQueryList; - msRequestAnimationFrame(callback: FrameRequestCallback): number; msWriteProfilerMark(profilerMarkName: string): void; open(url?: string, target?: string, features?: string, replace?: boolean): Window; - postMessage(message: any, targetOrigin: string, ports?: any): void; + postMessage(message: any, targetOrigin: string, transfer?: any[]): void; print(): void; prompt(message?: string, _default?: string): string; releaseEvents(): void; @@ -11997,8 +12991,10 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window scroll(x?: number, y?: number): void; scrollBy(x?: number, y?: number): void; scrollTo(x?: number, y?: number): void; + webkitCancelAnimationFrame(handle: number): void; webkitConvertPointFromNodeToPage(node: Node, pt: WebKitPoint): WebKitPoint; webkitConvertPointFromPageToNode(node: Node, pt: WebKitPoint): WebKitPoint; + webkitRequestAnimationFrame(callback: FrameRequestCallback): number; addEventListener(type: "MSGestureChange", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void; addEventListener(type: "MSGestureDoubleTap", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void; addEventListener(type: "MSGestureEnd", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void; @@ -12026,6 +13022,7 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window addEventListener(type: "compassneedscalibration", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "contextmenu", listener: (ev: PointerEvent) => any, useCapture?: boolean): void; addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; + addEventListener(type: "devicelight", listener: (ev: DeviceLightEvent) => any, useCapture?: boolean): void; addEventListener(type: "devicemotion", listener: (ev: DeviceMotionEvent) => any, useCapture?: boolean): void; addEventListener(type: "deviceorientation", listener: (ev: DeviceOrientationEvent) => any, useCapture?: boolean): void; addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void; @@ -12037,10 +13034,11 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void; addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void; - addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "ended", listener: (ev: MediaStreamErrorEvent) => any, useCapture?: boolean): void; addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void; addEventListener(type: "hashchange", listener: (ev: HashChangeEvent) => any, useCapture?: boolean): void; addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void; + addEventListener(type: "invalid", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; @@ -12056,7 +13054,7 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; - addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void; + addEventListener(type: "mousewheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void; addEventListener(type: "offline", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "online", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "orientationchange", listener: (ev: Event) => any, useCapture?: boolean): void; @@ -12128,7 +13126,6 @@ interface XMLHttpRequest extends EventTarget, XMLHttpRequestEventTarget { onreadystatechange: (ev: ProgressEvent) => any; readyState: number; response: any; - responseBody: any; responseText: string; responseType: string; responseXML: any; @@ -12280,6 +13277,18 @@ interface AbstractWorker { addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } +interface CanvasPathMethods { + arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, anticlockwise?: boolean): void; + arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void; + bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void; + closePath(): void; + ellipse(x: number, y: number, radiusX: number, radiusY: number, rotation: number, startAngle: number, endAngle: number, anticlockwise?: boolean): void; + lineTo(x: number, y: number): void; + moveTo(x: number, y: number): void; + quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void; + rect(x: number, y: number, w: number, h: number): void; +} + interface ChildNode { remove(): void; } @@ -12302,6 +13311,7 @@ interface DocumentEvent { createEvent(eventInterface:"CommandEvent"): CommandEvent; createEvent(eventInterface:"CompositionEvent"): CompositionEvent; createEvent(eventInterface:"CustomEvent"): CustomEvent; + createEvent(eventInterface:"DeviceLightEvent"): DeviceLightEvent; createEvent(eventInterface:"DeviceMotionEvent"): DeviceMotionEvent; createEvent(eventInterface:"DeviceOrientationEvent"): DeviceOrientationEvent; createEvent(eventInterface:"DragEvent"): DragEvent; @@ -12313,6 +13323,7 @@ interface DocumentEvent { createEvent(eventInterface:"HashChangeEvent"): HashChangeEvent; createEvent(eventInterface:"IDBVersionChangeEvent"): IDBVersionChangeEvent; createEvent(eventInterface:"KeyboardEvent"): KeyboardEvent; + createEvent(eventInterface:"ListeningStateChangedEvent"): ListeningStateChangedEvent; createEvent(eventInterface:"LongRunningScriptDetectedEvent"): LongRunningScriptDetectedEvent; createEvent(eventInterface:"MSGestureEvent"): MSGestureEvent; createEvent(eventInterface:"MSManipulationEvent"): MSManipulationEvent; @@ -12320,21 +13331,31 @@ interface DocumentEvent { createEvent(eventInterface:"MSMediaKeyNeededEvent"): MSMediaKeyNeededEvent; createEvent(eventInterface:"MSPointerEvent"): MSPointerEvent; createEvent(eventInterface:"MSSiteModeEvent"): MSSiteModeEvent; + createEvent(eventInterface:"MediaEncryptedEvent"): MediaEncryptedEvent; + createEvent(eventInterface:"MediaKeyMessageEvent"): MediaKeyMessageEvent; + createEvent(eventInterface:"MediaStreamErrorEvent"): MediaStreamErrorEvent; + createEvent(eventInterface:"MediaStreamTrackEvent"): MediaStreamTrackEvent; createEvent(eventInterface:"MessageEvent"): MessageEvent; createEvent(eventInterface:"MouseEvent"): MouseEvent; createEvent(eventInterface:"MouseEvents"): MouseEvent; - createEvent(eventInterface:"MouseWheelEvent"): MouseWheelEvent; createEvent(eventInterface:"MutationEvent"): MutationEvent; createEvent(eventInterface:"MutationEvents"): MutationEvent; createEvent(eventInterface:"NavigationCompletedEvent"): NavigationCompletedEvent; createEvent(eventInterface:"NavigationEvent"): NavigationEvent; createEvent(eventInterface:"NavigationEventWithReferrer"): NavigationEventWithReferrer; createEvent(eventInterface:"OfflineAudioCompletionEvent"): OfflineAudioCompletionEvent; + createEvent(eventInterface:"OverflowEvent"): OverflowEvent; createEvent(eventInterface:"PageTransitionEvent"): PageTransitionEvent; createEvent(eventInterface:"PermissionRequestedEvent"): PermissionRequestedEvent; createEvent(eventInterface:"PointerEvent"): PointerEvent; createEvent(eventInterface:"PopStateEvent"): PopStateEvent; createEvent(eventInterface:"ProgressEvent"): ProgressEvent; + createEvent(eventInterface:"RTCDTMFToneChangeEvent"): RTCDTMFToneChangeEvent; + createEvent(eventInterface:"RTCDtlsTransportStateChangedEvent"): RTCDtlsTransportStateChangedEvent; + createEvent(eventInterface:"RTCIceCandidatePairChangedEvent"): RTCIceCandidatePairChangedEvent; + createEvent(eventInterface:"RTCIceGathererEvent"): RTCIceGathererEvent; + createEvent(eventInterface:"RTCIceTransportStateChangedEvent"): RTCIceTransportStateChangedEvent; + createEvent(eventInterface:"RTCSsrcConflictEvent"): RTCSsrcConflictEvent; createEvent(eventInterface:"SVGZoomEvent"): SVGZoomEvent; createEvent(eventInterface:"SVGZoomEvents"): SVGZoomEvent; createEvent(eventInterface:"ScriptNotifyEvent"): ScriptNotifyEvent; @@ -12402,7 +13423,6 @@ interface HTMLTableAlignment { interface IDBEnvironment { indexedDB: IDBFactory; - msIndexedDB: IDBFactory; } interface LinkStyle { @@ -12470,6 +13490,11 @@ interface NavigatorOnLine { interface NavigatorStorageUtils { } +interface NavigatorUserMedia { + mediaDevices: MediaDevices; + getUserMedia(constraints: MediaStreamConstraints, successCallback: NavigatorUserMediaSuccessCallback, errorCallback: NavigatorUserMediaErrorCallback): void; +} + interface NodeSelector { querySelector(selectors: string): Element; querySelectorAll(selectors: string): NodeListOf; @@ -12565,8 +13590,6 @@ interface WindowTimers extends Object, WindowTimersExtension { interface WindowTimersExtension { clearImmediate(handle: number): void; - msClearImmediate(handle: number): void; - msSetImmediate(expression: any, ...args: any[]): number; setImmediate(expression: any, ...args: any[]): number; } @@ -12596,16 +13619,6 @@ interface StorageEventInit extends EventInit { storageArea?: Storage; } -interface IDBObjectStoreParameters { - keyPath?: string | string[]; - autoIncrement?: boolean; -} - -interface IDBIndexParameters { - unique?: boolean; - multiEntry?: boolean; -} - interface NodeListOf extends NodeList { length: number; item(index: number): TNode; @@ -12641,15 +13654,6 @@ interface ProgressEventInit extends EventInit { total?: number; } -interface HTMLTemplateElement extends HTMLElement { - content: DocumentFragment; -} - -declare var HTMLTemplateElement: { - prototype: HTMLTemplateElement; - new(): HTMLTemplateElement; -} - interface HTMLPictureElement extends HTMLElement { } @@ -12658,6 +13662,14 @@ declare var HTMLPictureElement: { new(): HTMLPictureElement; } +interface ClipboardEventInit extends EventInit { + data?: string; + dataType?: string; +} + +interface IDBArrayKey extends Array { +} + declare type EventListenerOrEventListenerObject = EventListener | EventListenerObject; interface ErrorEventHandler { @@ -12696,10 +13708,18 @@ interface DecodeErrorCallback { interface FunctionStringCallback { (data: string): void; } +interface NavigatorUserMediaSuccessCallback { + (stream: MediaStream): void; +} +interface NavigatorUserMediaErrorCallback { + (error: MediaStreamError): void; +} +interface ForEachCallback { + (keyId: any, status: string): void; +} declare var Audio: {new(src?: string): HTMLAudioElement; }; declare var Image: {new(width?: number, height?: number): HTMLImageElement; }; declare var Option: {new(text?: string, value?: string, defaultSelected?: boolean, selected?: boolean): HTMLOptionElement; }; -declare var animationStartTime: number; declare var applicationCache: ApplicationCache; declare var clientInformation: Navigator; declare var closed: boolean; @@ -12719,7 +13739,7 @@ declare var length: number; declare var location: Location; declare var locationbar: BarProp; declare var menubar: BarProp; -declare var msAnimationStartTime: number; +declare var msCredentials: MSCredentials; declare var name: string; declare var navigator: Navigator; declare var offscreenBuffering: string | boolean; @@ -12735,6 +13755,7 @@ declare var onclick: (ev: MouseEvent) => any; declare var oncompassneedscalibration: (ev: Event) => any; declare var oncontextmenu: (ev: PointerEvent) => any; declare var ondblclick: (ev: MouseEvent) => any; +declare var ondevicelight: (ev: DeviceLightEvent) => any; declare var ondevicemotion: (ev: DeviceMotionEvent) => any; declare var ondeviceorientation: (ev: DeviceOrientationEvent) => any; declare var ondrag: (ev: DragEvent) => any; @@ -12746,11 +13767,12 @@ declare var ondragstart: (ev: DragEvent) => any; declare var ondrop: (ev: DragEvent) => any; declare var ondurationchange: (ev: Event) => any; declare var onemptied: (ev: Event) => any; -declare var onended: (ev: Event) => any; +declare var onended: (ev: MediaStreamErrorEvent) => any; declare var onerror: ErrorEventHandler; declare var onfocus: (ev: FocusEvent) => any; declare var onhashchange: (ev: HashChangeEvent) => any; declare var oninput: (ev: Event) => any; +declare var oninvalid: (ev: Event) => any; declare var onkeydown: (ev: KeyboardEvent) => any; declare var onkeypress: (ev: KeyboardEvent) => any; declare var onkeyup: (ev: KeyboardEvent) => any; @@ -12766,7 +13788,7 @@ declare var onmousemove: (ev: MouseEvent) => any; declare var onmouseout: (ev: MouseEvent) => any; declare var onmouseover: (ev: MouseEvent) => any; declare var onmouseup: (ev: MouseEvent) => any; -declare var onmousewheel: (ev: MouseWheelEvent) => any; +declare var onmousewheel: (ev: WheelEvent) => any; declare var onmsgesturechange: (ev: MSGestureEvent) => any; declare var onmsgesturedoubletap: (ev: MSGestureEvent) => any; declare var onmsgestureend: (ev: MSGestureEvent) => any; @@ -12805,10 +13827,10 @@ declare var onstorage: (ev: StorageEvent) => any; declare var onsubmit: (ev: Event) => any; declare var onsuspend: (ev: Event) => any; declare var ontimeupdate: (ev: Event) => any; -declare var ontouchcancel: any; -declare var ontouchend: any; -declare var ontouchmove: any; -declare var ontouchstart: any; +declare var ontouchcancel: (ev: TouchEvent) => any; +declare var ontouchend: (ev: TouchEvent) => any; +declare var ontouchmove: (ev: TouchEvent) => any; +declare var ontouchstart: (ev: TouchEvent) => any; declare var onunload: (ev: Event) => any; declare var onvolumechange: (ev: Event) => any; declare var onwaiting: (ev: Event) => any; @@ -12836,7 +13858,6 @@ declare var styleMedia: StyleMedia; declare var toolbar: BarProp; declare var top: Window; declare var window: Window; -declare var URL: URL; declare function alert(message?: any): void; declare function blur(): void; declare function cancelAnimationFrame(handle: number): void; @@ -12850,12 +13871,9 @@ declare function getSelection(): Selection; declare function matchMedia(mediaQuery: string): MediaQueryList; declare function moveBy(x?: number, y?: number): void; declare function moveTo(x?: number, y?: number): void; -declare function msCancelRequestAnimationFrame(handle: number): void; -declare function msMatchMedia(mediaQuery: string): MediaQueryList; -declare function msRequestAnimationFrame(callback: FrameRequestCallback): number; declare function msWriteProfilerMark(profilerMarkName: string): void; declare function open(url?: string, target?: string, features?: string, replace?: boolean): Window; -declare function postMessage(message: any, targetOrigin: string, ports?: any): void; +declare function postMessage(message: any, targetOrigin: string, transfer?: any[]): void; declare function print(): void; declare function prompt(message?: string, _default?: string): string; declare function releaseEvents(): void; @@ -12865,19 +13883,19 @@ declare function resizeTo(x?: number, y?: number): void; declare function scroll(x?: number, y?: number): void; declare function scrollBy(x?: number, y?: number): void; declare function scrollTo(x?: number, y?: number): void; +declare function webkitCancelAnimationFrame(handle: number): void; declare function webkitConvertPointFromNodeToPage(node: Node, pt: WebKitPoint): WebKitPoint; declare function webkitConvertPointFromPageToNode(node: Node, pt: WebKitPoint): WebKitPoint; +declare function webkitRequestAnimationFrame(callback: FrameRequestCallback): number; declare function toString(): string; -declare function addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +declare function addEventListener(type: string, listener?: EventListenerOrEventListenerObject, useCapture?: boolean): void; declare function dispatchEvent(evt: Event): boolean; -declare function removeEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +declare function removeEventListener(type: string, listener?: EventListenerOrEventListenerObject, useCapture?: boolean): void; declare function clearInterval(handle: number): void; declare function clearTimeout(handle: number): void; declare function setInterval(handler: any, timeout?: any, ...args: any[]): number; declare function setTimeout(handler: any, timeout?: any, ...args: any[]): number; declare function clearImmediate(handle: number): void; -declare function msClearImmediate(handle: number): void; -declare function msSetImmediate(expression: any, ...args: any[]): number; declare function setImmediate(expression: any, ...args: any[]): number; declare var sessionStorage: Storage; declare var localStorage: Storage; @@ -12892,7 +13910,6 @@ declare var onpointerover: (ev: PointerEvent) => any; declare var onpointerup: (ev: PointerEvent) => any; declare var onwheel: (ev: WheelEvent) => any; declare var indexedDB: IDBFactory; -declare var msIndexedDB: IDBFactory; declare function atob(encodedString: string): string; declare function btoa(rawString: string): string; declare function addEventListener(type: "MSGestureChange", listener: (ev: MSGestureEvent) => any, useCapture?: boolean): void; @@ -12922,6 +13939,7 @@ declare function addEventListener(type: "click", listener: (ev: MouseEvent) => a declare function addEventListener(type: "compassneedscalibration", listener: (ev: Event) => any, useCapture?: boolean): void; declare function addEventListener(type: "contextmenu", listener: (ev: PointerEvent) => any, useCapture?: boolean): void; declare function addEventListener(type: "dblclick", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; +declare function addEventListener(type: "devicelight", listener: (ev: DeviceLightEvent) => any, useCapture?: boolean): void; declare function addEventListener(type: "devicemotion", listener: (ev: DeviceMotionEvent) => any, useCapture?: boolean): void; declare function addEventListener(type: "deviceorientation", listener: (ev: DeviceOrientationEvent) => any, useCapture?: boolean): void; declare function addEventListener(type: "drag", listener: (ev: DragEvent) => any, useCapture?: boolean): void; @@ -12933,10 +13951,11 @@ declare function addEventListener(type: "dragstart", listener: (ev: DragEvent) = declare function addEventListener(type: "drop", listener: (ev: DragEvent) => any, useCapture?: boolean): void; declare function addEventListener(type: "durationchange", listener: (ev: Event) => any, useCapture?: boolean): void; declare function addEventListener(type: "emptied", listener: (ev: Event) => any, useCapture?: boolean): void; -declare function addEventListener(type: "ended", listener: (ev: Event) => any, useCapture?: boolean): void; +declare function addEventListener(type: "ended", listener: (ev: MediaStreamErrorEvent) => any, useCapture?: boolean): void; declare function addEventListener(type: "focus", listener: (ev: FocusEvent) => any, useCapture?: boolean): void; declare function addEventListener(type: "hashchange", listener: (ev: HashChangeEvent) => any, useCapture?: boolean): void; declare function addEventListener(type: "input", listener: (ev: Event) => any, useCapture?: boolean): void; +declare function addEventListener(type: "invalid", listener: (ev: Event) => any, useCapture?: boolean): void; declare function addEventListener(type: "keydown", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; declare function addEventListener(type: "keypress", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; declare function addEventListener(type: "keyup", listener: (ev: KeyboardEvent) => any, useCapture?: boolean): void; @@ -12952,7 +13971,7 @@ declare function addEventListener(type: "mousemove", listener: (ev: MouseEvent) declare function addEventListener(type: "mouseout", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; declare function addEventListener(type: "mouseover", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; declare function addEventListener(type: "mouseup", listener: (ev: MouseEvent) => any, useCapture?: boolean): void; -declare function addEventListener(type: "mousewheel", listener: (ev: MouseWheelEvent) => any, useCapture?: boolean): void; +declare function addEventListener(type: "mousewheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void; declare function addEventListener(type: "offline", listener: (ev: Event) => any, useCapture?: boolean): void; declare function addEventListener(type: "online", listener: (ev: Event) => any, useCapture?: boolean): void; declare function addEventListener(type: "orientationchange", listener: (ev: Event) => any, useCapture?: boolean): void; @@ -12988,4 +14007,36 @@ declare function addEventListener(type: "unload", listener: (ev: Event) => any, declare function addEventListener(type: "volumechange", listener: (ev: Event) => any, useCapture?: boolean): void; declare function addEventListener(type: "waiting", listener: (ev: Event) => any, useCapture?: boolean): void; declare function addEventListener(type: "wheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void; -declare function addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; \ No newline at end of file +declare function addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +type AAGUID = string; +type AlgorithmIdentifier = string | Algorithm; +type ConstrainBoolean = boolean | ConstrainBooleanParameters; +type ConstrainDOMString = string | string[] | ConstrainDOMStringParameters; +type ConstrainDouble = number | ConstrainDoubleRange; +type ConstrainLong = number | ConstrainLongRange; +type CryptoOperationData = ArrayBufferView; +type GLbitfield = number; +type GLboolean = boolean; +type GLbyte = number; +type GLclampf = number; +type GLenum = number; +type GLfloat = number; +type GLint = number; +type GLintptr = number; +type GLshort = number; +type GLsizei = number; +type GLsizeiptr = number; +type GLubyte = number; +type GLuint = number; +type GLushort = number; +type IDBKeyPath = string; +type KeyFormat = string; +type KeyType = string; +type KeyUsage = string; +type MSInboundPayload = MSVideoRecvPayload | MSAudioRecvPayload; +type MSLocalClientEvent = MSLocalClientEventBase | MSAudioLocalClientEvent; +type MSOutboundPayload = MSVideoSendPayload | MSAudioSendPayload; +type RTCIceGatherCandidate = RTCIceCandidate | RTCIceCandidateComplete; +type RTCTransport = RTCDtlsTransport | RTCSrtpSdesTransport; +type payloadtype = number; +type IDBValidKey = number | string | Date | IDBArrayKey; \ No newline at end of file diff --git a/src/lib/webworker.generated.d.ts b/src/lib/webworker.generated.d.ts index cd49a565f12..b342c88a9fd 100644 --- a/src/lib/webworker.generated.d.ts +++ b/src/lib/webworker.generated.d.ts @@ -17,6 +17,8 @@ interface AudioBuffer { length: number; numberOfChannels: number; sampleRate: number; + copyFromChannel(destination: Float32Array, channelNumber: number, startInChannel?: number): void; + copyToChannel(source: Float32Array, channelNumber: number, startInChannel?: number): void; getChannelData(channel: number): Float32Array; } @@ -58,6 +60,7 @@ interface Console { dir(value?: any, ...optionalParams: any[]): void; dirxml(value: any): void; error(message?: any, ...optionalParams: any[]): void; + exception(message?: string, ...optionalParams: any[]): void; group(groupTitle?: string): void; groupCollapsed(groupTitle?: string): void; groupEnd(): void; @@ -67,6 +70,7 @@ interface Console { profile(reportName?: string): void; profileEnd(): void; select(element: any): void; + table(...data: any[]): void; time(timerName?: string): void; timeEnd(timerName?: string): void; trace(message?: any, ...optionalParams: any[]): void; @@ -226,9 +230,9 @@ declare var Event: { } interface EventTarget { - addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; + addEventListener(type: string, listener?: EventListenerOrEventListenerObject, useCapture?: boolean): void; dispatchEvent(evt: Event): boolean; - removeEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; + removeEventListener(type: string, listener?: EventListenerOrEventListenerObject, useCapture?: boolean): void; } declare var EventTarget: { @@ -239,6 +243,7 @@ declare var EventTarget: { interface File extends Blob { lastModifiedDate: any; name: string; + webkitRelativePath: string; } declare var File: { @@ -273,11 +278,11 @@ declare var FileReader: { interface IDBCursor { direction: string; - key: any; + key: IDBKeyRange | IDBValidKey; primaryKey: any; source: IDBObjectStore | IDBIndex; advance(count: number): void; - continue(key?: any): void; + continue(key?: IDBKeyRange | IDBValidKey): void; delete(): IDBRequest; update(value: any): IDBRequest; NEXT: string; @@ -310,10 +315,12 @@ interface IDBDatabase extends EventTarget { onabort: (ev: Event) => any; onerror: (ev: Event) => any; version: number; + onversionchange: (ev: IDBVersionChangeEvent) => any; close(): void; createObjectStore(name: string, optionalParameters?: IDBObjectStoreParameters): IDBObjectStore; deleteObjectStore(name: string): void; transaction(storeNames: string | string[], mode?: string): IDBTransaction; + addEventListener(type: "versionchange", listener: (ev: IDBVersionChangeEvent) => any, useCapture?: boolean): void; addEventListener(type: "abort", listener: (ev: Event) => any, useCapture?: boolean): void; addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; @@ -341,11 +348,11 @@ interface IDBIndex { objectStore: IDBObjectStore; unique: boolean; multiEntry: boolean; - count(key?: any): IDBRequest; - get(key: any): IDBRequest; - getKey(key: any): IDBRequest; - openCursor(range?: IDBKeyRange, direction?: string): IDBRequest; - openKeyCursor(range?: IDBKeyRange, direction?: string): IDBRequest; + count(key?: IDBKeyRange | IDBValidKey): IDBRequest; + get(key: IDBKeyRange | IDBValidKey): IDBRequest; + getKey(key: IDBKeyRange | IDBValidKey): IDBRequest; + openCursor(range?: IDBKeyRange | IDBValidKey, direction?: string): IDBRequest; + openKeyCursor(range?: IDBKeyRange | IDBValidKey, direction?: string): IDBRequest; } declare var IDBIndex: { @@ -364,9 +371,9 @@ declare var IDBKeyRange: { prototype: IDBKeyRange; new(): IDBKeyRange; bound(lower: any, upper: any, lowerOpen?: boolean, upperOpen?: boolean): IDBKeyRange; - lowerBound(bound: any, open?: boolean): IDBKeyRange; + lowerBound(lower: any, open?: boolean): IDBKeyRange; only(value: any): IDBKeyRange; - upperBound(bound: any, open?: boolean): IDBKeyRange; + upperBound(upper: any, open?: boolean): IDBKeyRange; } interface IDBObjectStore { @@ -375,16 +382,16 @@ interface IDBObjectStore { name: string; transaction: IDBTransaction; autoIncrement: boolean; - add(value: any, key?: any): IDBRequest; + add(value: any, key?: IDBKeyRange | IDBValidKey): IDBRequest; clear(): IDBRequest; - count(key?: any): IDBRequest; + count(key?: IDBKeyRange | IDBValidKey): IDBRequest; createIndex(name: string, keyPath: string | string[], optionalParameters?: IDBIndexParameters): IDBIndex; - delete(key: any): IDBRequest; + delete(key: IDBKeyRange | IDBValidKey): IDBRequest; deleteIndex(indexName: string): void; get(key: any): IDBRequest; index(name: string): IDBIndex; - openCursor(range?: any, direction?: string): IDBRequest; - put(value: any, key?: any): IDBRequest; + openCursor(range?: IDBKeyRange | IDBValidKey, direction?: string): IDBRequest; + put(value: any, key?: IDBKeyRange | IDBValidKey): IDBRequest; } declare var IDBObjectStore: { @@ -483,7 +490,7 @@ interface MSApp { execAsyncAtPriority(asynchronousCallback: MSExecAtPriorityFunctionCallback, priority: string, ...args: any[]): void; execAtPriority(synchronousCallback: MSExecAtPriorityFunctionCallback, priority: string, ...args: any[]): any; getCurrentPriority(): string; - getHtmlPrintDocumentSourceAsync(htmlDoc: any): any; + getHtmlPrintDocumentSourceAsync(htmlDoc: any): PromiseLike; getViewId(view: any): any; isTaskScheduledAtPriorityOrHigher(priority: string): boolean; pageHandlesAllApplicationActivations(enabled: boolean): void; @@ -695,7 +702,6 @@ interface XMLHttpRequest extends EventTarget, XMLHttpRequestEventTarget { onreadystatechange: (ev: ProgressEvent) => any; readyState: number; response: any; - responseBody: any; responseText: string; responseType: string; responseXML: any; @@ -894,16 +900,6 @@ interface WorkerUtils extends Object, WindowBase64 { setTimeout(handler: any, timeout?: any, ...args: any[]): number; } -interface IDBObjectStoreParameters { - keyPath?: string | string[]; - autoIncrement?: boolean; -} - -interface IDBIndexParameters { - unique?: boolean; - multiEntry?: boolean; -} - interface BlobPropertyBag { type?: string; endings?: string; @@ -933,6 +929,9 @@ interface ProgressEventInit extends EventInit { total?: number; } +interface IDBArrayKey extends Array { +} + declare type EventListenerOrEventListenerObject = EventListener | EventListenerObject; interface ErrorEventHandler { @@ -971,9 +970,9 @@ declare var self: WorkerGlobalScope; declare function close(): void; declare function msWriteProfilerMark(profilerMarkName: string): void; declare function toString(): string; -declare function addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +declare function addEventListener(type: string, listener?: EventListenerOrEventListenerObject, useCapture?: boolean): void; declare function dispatchEvent(evt: Event): boolean; -declare function removeEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +declare function removeEventListener(type: string, listener?: EventListenerOrEventListenerObject, useCapture?: boolean): void; declare var indexedDB: IDBFactory; declare var msIndexedDB: IDBFactory; declare var navigator: WorkerNavigator; @@ -991,4 +990,5 @@ declare function postMessage(data: any): void; declare var console: Console; declare function addEventListener(type: "error", listener: (ev: ErrorEvent) => any, useCapture?: boolean): void; declare function addEventListener(type: "message", listener: (ev: MessageEvent) => any, useCapture?: boolean): void; -declare function addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; \ No newline at end of file +declare function addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +type IDBValidKey = number | string | Date | IDBArrayKey; \ No newline at end of file From 6f37d31e18d3fdf68dee1ce83b5ddc08dd850a79 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Mon, 21 Mar 2016 15:15:41 -0700 Subject: [PATCH 128/274] drop inference limit --- src/compiler/checker.ts | 6 - tests/baselines/reference/inferenceLimit.js | 82 ++++++++++++ .../reference/inferenceLimit.symbols | 101 ++++++++++++++ .../baselines/reference/inferenceLimit.types | 123 ++++++++++++++++++ tests/cases/compiler/inferenceLimit.ts | 41 ++++++ 5 files changed, 347 insertions(+), 6 deletions(-) create mode 100644 tests/baselines/reference/inferenceLimit.js create mode 100644 tests/baselines/reference/inferenceLimit.symbols create mode 100644 tests/baselines/reference/inferenceLimit.types create mode 100644 tests/cases/compiler/inferenceLimit.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b7779fc9da0..90ded8fc6bc 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6673,7 +6673,6 @@ namespace ts { function inferTypes(context: InferenceContext, source: Type, target: Type) { let sourceStack: Type[]; let targetStack: Type[]; - const maxDepth = 5; let depth = 0; let inferiority = 0; const visited: Map = {}; @@ -6802,11 +6801,6 @@ namespace ts { if (isInProcess(source, target)) { return; } - // we delibirately limit the depth we examine to infer types: this speeds up the overall inference process - // and user rarely expects inferences to be made from the deeply nested constituents. - if (depth > maxDepth) { - return; - } if (isDeeplyNestedGeneric(source, sourceStack, depth) && isDeeplyNestedGeneric(target, targetStack, depth)) { return; } diff --git a/tests/baselines/reference/inferenceLimit.js b/tests/baselines/reference/inferenceLimit.js new file mode 100644 index 00000000000..a74bf59df44 --- /dev/null +++ b/tests/baselines/reference/inferenceLimit.js @@ -0,0 +1,82 @@ +//// [tests/cases/compiler/inferenceLimit.ts] //// + +//// [file1.ts] +"use strict"; +import * as MyModule from "./mymodule"; + +export class BrokenClass { + + constructor() {} + + public brokenMethod(field: string, value: string) { + return new Promise>((resolve, reject) => { + + let result: Array = []; + + let populateItems = (order) => { + return new Promise((resolve, reject) => { + this.doStuff(order.id) + .then((items) => { + order.items = items; + resolve(order); + }); + }); + }; + + return Promise.all(result.map(populateItems)) + .then((orders: Array) => { + resolve(orders); + }); + }); + } + + public async doStuff(id: number) { + return; + } +} + +//// [mymodule.ts] +export interface MyModel { + id: number; +} + +//// [mymodule.js] +"use strict"; +//// [file1.js] +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments)).next()); + }); +}; +class BrokenClass { + constructor() { + } + brokenMethod(field, value) { + return new Promise((resolve, reject) => { + let result = []; + let populateItems = (order) => { + return new Promise((resolve, reject) => { + this.doStuff(order.id) + .then((items) => { + order.items = items; + resolve(order); + }); + }); + }; + return Promise.all(result.map(populateItems)) + .then((orders) => { + resolve(orders); + }); + }); + } + doStuff(id) { + return __awaiter(this, void 0, void 0, function* () { + return; + }); + } +} +exports.BrokenClass = BrokenClass; diff --git a/tests/baselines/reference/inferenceLimit.symbols b/tests/baselines/reference/inferenceLimit.symbols new file mode 100644 index 00000000000..8a338b80307 --- /dev/null +++ b/tests/baselines/reference/inferenceLimit.symbols @@ -0,0 +1,101 @@ +=== tests/cases/compiler/file1.ts === +"use strict"; +import * as MyModule from "./mymodule"; +>MyModule : Symbol(MyModule, Decl(file1.ts, 1, 6)) + +export class BrokenClass { +>BrokenClass : Symbol(BrokenClass, Decl(file1.ts, 1, 39)) + + constructor() {} + + public brokenMethod(field: string, value: string) { +>brokenMethod : Symbol(BrokenClass.brokenMethod, Decl(file1.ts, 5, 18)) +>field : Symbol(field, Decl(file1.ts, 7, 22)) +>value : Symbol(value, Decl(file1.ts, 7, 36)) + + return new Promise>((resolve, reject) => { +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>MyModule : Symbol(MyModule, Decl(file1.ts, 1, 6)) +>MyModel : Symbol(MyModule.MyModel, Decl(mymodule.ts, 0, 0)) +>resolve : Symbol(resolve, Decl(file1.ts, 8, 47)) +>reject : Symbol(reject, Decl(file1.ts, 8, 55)) + + let result: Array = []; +>result : Symbol(result, Decl(file1.ts, 10, 7)) +>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>MyModule : Symbol(MyModule, Decl(file1.ts, 1, 6)) +>MyModel : Symbol(MyModule.MyModel, Decl(mymodule.ts, 0, 0)) + + let populateItems = (order) => { +>populateItems : Symbol(populateItems, Decl(file1.ts, 12, 7)) +>order : Symbol(order, Decl(file1.ts, 12, 25)) + + return new Promise((resolve, reject) => { +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>resolve : Symbol(resolve, Decl(file1.ts, 13, 26)) +>reject : Symbol(reject, Decl(file1.ts, 13, 34)) + + this.doStuff(order.id) +>this.doStuff(order.id) .then : Symbol(Promise.then, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>this.doStuff : Symbol(BrokenClass.doStuff, Decl(file1.ts, 27, 3)) +>this : Symbol(BrokenClass, Decl(file1.ts, 1, 39)) +>doStuff : Symbol(BrokenClass.doStuff, Decl(file1.ts, 27, 3)) +>order : Symbol(order, Decl(file1.ts, 12, 25)) + + .then((items) => { +>then : Symbol(Promise.then, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>items : Symbol(items, Decl(file1.ts, 15, 17)) + + order.items = items; +>order : Symbol(order, Decl(file1.ts, 12, 25)) +>items : Symbol(items, Decl(file1.ts, 15, 17)) + + resolve(order); +>resolve : Symbol(resolve, Decl(file1.ts, 13, 26)) +>order : Symbol(order, Decl(file1.ts, 12, 25)) + + }); + }); + }; + + return Promise.all(result.map(populateItems)) +>Promise.all(result.map(populateItems)) .then : Symbol(Promise.then, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>Promise.all : Symbol(PromiseConstructor.all, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>all : Symbol(PromiseConstructor.all, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>result.map : Symbol(Array.map, Decl(lib.d.ts, --, --)) +>result : Symbol(result, Decl(file1.ts, 10, 7)) +>map : Symbol(Array.map, Decl(lib.d.ts, --, --)) +>populateItems : Symbol(populateItems, Decl(file1.ts, 12, 7)) + + .then((orders: Array) => { +>then : Symbol(Promise.then, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>orders : Symbol(orders, Decl(file1.ts, 23, 13)) +>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>MyModule : Symbol(MyModule, Decl(file1.ts, 1, 6)) +>MyModel : Symbol(MyModule.MyModel, Decl(mymodule.ts, 0, 0)) + + resolve(orders); +>resolve : Symbol(resolve, Decl(file1.ts, 8, 47)) +>orders : Symbol(orders, Decl(file1.ts, 23, 13)) + + }); + }); + } + + public async doStuff(id: number) { +>doStuff : Symbol(BrokenClass.doStuff, Decl(file1.ts, 27, 3)) +>id : Symbol(id, Decl(file1.ts, 29, 23)) + + return; + } +} + +=== tests/cases/compiler/mymodule.ts === +export interface MyModel { +>MyModel : Symbol(MyModel, Decl(mymodule.ts, 0, 0)) + + id: number; +>id : Symbol(MyModel.id, Decl(mymodule.ts, 0, 26)) +} diff --git a/tests/baselines/reference/inferenceLimit.types b/tests/baselines/reference/inferenceLimit.types new file mode 100644 index 00000000000..58f9b1e4ae0 --- /dev/null +++ b/tests/baselines/reference/inferenceLimit.types @@ -0,0 +1,123 @@ +=== tests/cases/compiler/file1.ts === +"use strict"; +>"use strict" : string + +import * as MyModule from "./mymodule"; +>MyModule : typeof MyModule + +export class BrokenClass { +>BrokenClass : BrokenClass + + constructor() {} + + public brokenMethod(field: string, value: string) { +>brokenMethod : (field: string, value: string) => Promise +>field : string +>value : string + + return new Promise>((resolve, reject) => { +>new Promise>((resolve, reject) => { let result: Array = []; let populateItems = (order) => { return new Promise((resolve, reject) => { this.doStuff(order.id) .then((items) => { order.items = items; resolve(order); }); }); }; return Promise.all(result.map(populateItems)) .then((orders: Array) => { resolve(orders); }); }) : Promise +>Promise : PromiseConstructor +>Array : T[] +>MyModule : any +>MyModel : MyModule.MyModel +>(resolve, reject) => { let result: Array = []; let populateItems = (order) => { return new Promise((resolve, reject) => { this.doStuff(order.id) .then((items) => { order.items = items; resolve(order); }); }); }; return Promise.all(result.map(populateItems)) .then((orders: Array) => { resolve(orders); }); } : (resolve: (value?: MyModule.MyModel[] | PromiseLike) => void, reject: (reason?: any) => void) => Promise +>resolve : (value?: MyModule.MyModel[] | PromiseLike) => void +>reject : (reason?: any) => void + + let result: Array = []; +>result : MyModule.MyModel[] +>Array : T[] +>MyModule : any +>MyModel : MyModule.MyModel +>[] : undefined[] + + let populateItems = (order) => { +>populateItems : (order: any) => Promise<{}> +>(order) => { return new Promise((resolve, reject) => { this.doStuff(order.id) .then((items) => { order.items = items; resolve(order); }); }); } : (order: any) => Promise<{}> +>order : any + + return new Promise((resolve, reject) => { +>new Promise((resolve, reject) => { this.doStuff(order.id) .then((items) => { order.items = items; resolve(order); }); }) : Promise<{}> +>Promise : PromiseConstructor +>(resolve, reject) => { this.doStuff(order.id) .then((items) => { order.items = items; resolve(order); }); } : (resolve: (value?: {} | PromiseLike<{}>) => void, reject: (reason?: any) => void) => void +>resolve : (value?: {} | PromiseLike<{}>) => void +>reject : (reason?: any) => void + + this.doStuff(order.id) +>this.doStuff(order.id) .then((items) => { order.items = items; resolve(order); }) : Promise +>this.doStuff(order.id) .then : { (onfulfilled?: (value: void) => TResult | PromiseLike, onrejected?: (reason: any) => TResult | PromiseLike): Promise; (onfulfilled?: (value: void) => TResult | PromiseLike, onrejected?: (reason: any) => void): Promise; } +>this.doStuff(order.id) : Promise +>this.doStuff : (id: number) => Promise +>this : this +>doStuff : (id: number) => Promise +>order.id : any +>order : any +>id : any + + .then((items) => { +>then : { (onfulfilled?: (value: void) => TResult | PromiseLike, onrejected?: (reason: any) => TResult | PromiseLike): Promise; (onfulfilled?: (value: void) => TResult | PromiseLike, onrejected?: (reason: any) => void): Promise; } +>(items) => { order.items = items; resolve(order); } : (items: void) => void +>items : void + + order.items = items; +>order.items = items : void +>order.items : any +>order : any +>items : any +>items : void + + resolve(order); +>resolve(order) : void +>resolve : (value?: {} | PromiseLike<{}>) => void +>order : any + + }); + }); + }; + + return Promise.all(result.map(populateItems)) +>Promise.all(result.map(populateItems)) .then((orders: Array) => { resolve(orders); }) : Promise +>Promise.all(result.map(populateItems)) .then : { (onfulfilled?: (value: {}[]) => TResult | PromiseLike, onrejected?: (reason: any) => TResult | PromiseLike): Promise; (onfulfilled?: (value: {}[]) => TResult | PromiseLike, onrejected?: (reason: any) => void): Promise; } +>Promise.all(result.map(populateItems)) : Promise<{}[]> +>Promise.all : { (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike, T9 | PromiseLike, T10 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike, T9 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike]): Promise<[T1, T2, T3, T4, T5]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike]): Promise<[T1, T2, T3, T4]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike]): Promise<[T1, T2, T3]>; (values: [T1 | PromiseLike, T2 | PromiseLike]): Promise<[T1, T2]>; (values: Iterable>): Promise; } +>Promise : PromiseConstructor +>all : { (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike, T9 | PromiseLike, T10 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike, T9 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike]): Promise<[T1, T2, T3, T4, T5]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike]): Promise<[T1, T2, T3, T4]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike]): Promise<[T1, T2, T3]>; (values: [T1 | PromiseLike, T2 | PromiseLike]): Promise<[T1, T2]>; (values: Iterable>): Promise; } +>result.map(populateItems) : Promise<{}>[] +>result.map : (callbackfn: (value: MyModule.MyModel, index: number, array: MyModule.MyModel[]) => U, thisArg?: any) => U[] +>result : MyModule.MyModel[] +>map : (callbackfn: (value: MyModule.MyModel, index: number, array: MyModule.MyModel[]) => U, thisArg?: any) => U[] +>populateItems : (order: any) => Promise<{}> + + .then((orders: Array) => { +>then : { (onfulfilled?: (value: {}[]) => TResult | PromiseLike, onrejected?: (reason: any) => TResult | PromiseLike): Promise; (onfulfilled?: (value: {}[]) => TResult | PromiseLike, onrejected?: (reason: any) => void): Promise; } +>(orders: Array) => { resolve(orders); } : (orders: MyModule.MyModel[]) => void +>orders : MyModule.MyModel[] +>Array : T[] +>MyModule : any +>MyModel : MyModule.MyModel + + resolve(orders); +>resolve(orders) : void +>resolve : (value?: MyModule.MyModel[] | PromiseLike) => void +>orders : MyModule.MyModel[] + + }); + }); + } + + public async doStuff(id: number) { +>doStuff : (id: number) => Promise +>id : number + + return; + } +} + +=== tests/cases/compiler/mymodule.ts === +export interface MyModel { +>MyModel : MyModel + + id: number; +>id : number +} diff --git a/tests/cases/compiler/inferenceLimit.ts b/tests/cases/compiler/inferenceLimit.ts new file mode 100644 index 00000000000..adaf13bad22 --- /dev/null +++ b/tests/cases/compiler/inferenceLimit.ts @@ -0,0 +1,41 @@ +// @target: es6 +// @module: commonjs +// @filename: file1.ts +"use strict"; +import * as MyModule from "./mymodule"; + +export class BrokenClass { + + constructor() {} + + public brokenMethod(field: string, value: string) { + return new Promise>((resolve, reject) => { + + let result: Array = []; + + let populateItems = (order) => { + return new Promise((resolve, reject) => { + this.doStuff(order.id) + .then((items) => { + order.items = items; + resolve(order); + }); + }); + }; + + return Promise.all(result.map(populateItems)) + .then((orders: Array) => { + resolve(orders); + }); + }); + } + + public async doStuff(id: number) { + return; + } +} + +// @filename: mymodule.ts +export interface MyModel { + id: number; +} \ No newline at end of file From 134a253f57a529bbdc9f7a74cff05d54e0b25f21 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Mon, 21 Mar 2016 15:20:59 -0700 Subject: [PATCH 129/274] added API sample to tests --- .../reference/APISample_parseConfig.js | 70 +++++++++++++++++++ tests/cases/compiler/APISample_parseConfig.ts | 39 +++++++++++ 2 files changed, 109 insertions(+) create mode 100644 tests/baselines/reference/APISample_parseConfig.js create mode 100644 tests/cases/compiler/APISample_parseConfig.ts diff --git a/tests/baselines/reference/APISample_parseConfig.js b/tests/baselines/reference/APISample_parseConfig.js new file mode 100644 index 00000000000..1312f8a4f81 --- /dev/null +++ b/tests/baselines/reference/APISample_parseConfig.js @@ -0,0 +1,70 @@ +//// [APISample_parseConfig.ts] + +/* + * Note: This test is a public API sample. The sample sources can be found + at: https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#a-minimal-compiler + * Please log a "breaking change" issue for any API breaking change affecting this issue + */ + +declare var process: any; +declare var console: any; +declare var os: any; + +import ts = require("typescript"); + +function printError(error: ts.Diagnostic): void { + if (!error) { + return; + } + console.log(`${error.file && error.file.fileName}: ${error.messageText}`); +} + +export function createProgram(rootFiles: string[], compilerOptionsJson: string): ts.Program { + const { config, error } = ts.parseConfigFileTextToJson("tsconfig.json", compilerOptionsJson) + if (error) { + printError(error); + return undefined; + } + const basePath: string = process.cwd(); + const settings = ts.convertCompilerOptionsFromJson(config.config["compilerOptions"], basePath); + if (!settings.options) { + for (const err of settings.errors) { + printError(err); + } + return undefined; + } + return ts.createProgram(rootFiles, settings.options); +} + +//// [APISample_parseConfig.js] +/* + * Note: This test is a public API sample. The sample sources can be found + at: https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#a-minimal-compiler + * Please log a "breaking change" issue for any API breaking change affecting this issue + */ +"use strict"; +var ts = require("typescript"); +function printError(error) { + if (!error) { + return; + } + console.log((error.file && error.file.fileName) + ": " + error.messageText); +} +function createProgram(rootFiles, compilerOptionsJson) { + var _a = ts.parseConfigFileTextToJson("tsconfig.json", compilerOptionsJson), config = _a.config, error = _a.error; + if (error) { + printError(error); + return undefined; + } + var basePath = process.cwd(); + var settings = ts.convertCompilerOptionsFromJson(config.config["compilerOptions"], basePath); + if (!settings.options) { + for (var _i = 0, _b = settings.errors; _i < _b.length; _i++) { + var err = _b[_i]; + printError(err); + } + return undefined; + } + return ts.createProgram(rootFiles, settings.options); +} +exports.createProgram = createProgram; diff --git a/tests/cases/compiler/APISample_parseConfig.ts b/tests/cases/compiler/APISample_parseConfig.ts new file mode 100644 index 00000000000..3e88e50727e --- /dev/null +++ b/tests/cases/compiler/APISample_parseConfig.ts @@ -0,0 +1,39 @@ +// @module: commonjs +// @includebuiltfile: typescript_standalone.d.ts +// @stripInternal:true + +/* + * Note: This test is a public API sample. The sample sources can be found + at: https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#a-minimal-compiler + * Please log a "breaking change" issue for any API breaking change affecting this issue + */ + +declare var process: any; +declare var console: any; +declare var os: any; + +import ts = require("typescript"); + +function printError(error: ts.Diagnostic): void { + if (!error) { + return; + } + console.log(`${error.file && error.file.fileName}: ${error.messageText}`); +} + +export function createProgram(rootFiles: string[], compilerOptionsJson: string): ts.Program { + const { config, error } = ts.parseConfigFileTextToJson("tsconfig.json", compilerOptionsJson) + if (error) { + printError(error); + return undefined; + } + const basePath: string = process.cwd(); + const settings = ts.convertCompilerOptionsFromJson(config.config["compilerOptions"], basePath); + if (!settings.options) { + for (const err of settings.errors) { + printError(err); + } + return undefined; + } + return ts.createProgram(rootFiles, settings.options); +} \ No newline at end of file From d5c3a0a52b3c40f71de8acd98769fd9004c04264 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 21 Mar 2016 15:40:14 -0700 Subject: [PATCH 130/274] Fix issue with find references for jsx tags --- src/compiler/checker.ts | 3 +++ .../reference/jsxReactTestSuite.symbols | 24 +++++++++++++++++++ .../reference/reactNamespaceJSXEmit.symbols | 3 +++ .../reference/tsxElementResolution19.symbols | 2 +- .../reference/tsxExternalModuleEmit1.symbols | 2 +- .../reference/tsxExternalModuleEmit2.symbols | 4 ++++ .../tsxGenericArrowFunctionParsing.symbols | 6 +++++ .../reference/tsxPreserveEmit1.symbols | 3 +++ .../reference/tsxPreserveEmit2.symbols | 1 + .../baselines/reference/tsxReactEmit3.symbols | 8 +++++++ .../tsxStatelessFunctionComponents3.symbols | 4 ++-- .../fourslash/findReferencesJSXTagName.ts | 22 +++++++++++++++++ 12 files changed, 78 insertions(+), 4 deletions(-) create mode 100644 tests/cases/fourslash/findReferencesJSXTagName.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b7779fc9da0..c94027b40ac 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8755,6 +8755,9 @@ namespace ts { if (isJsxIntrinsicIdentifier(node.tagName)) { return getIntrinsicTagSymbol(node); } + else if (node.tagName.kind === SyntaxKind.Identifier) { + return resolveEntityName(node.tagName, SymbolFlags.Value | SymbolFlags.Alias); + } else { return checkExpression(node.tagName).symbol; } diff --git a/tests/baselines/reference/jsxReactTestSuite.symbols b/tests/baselines/reference/jsxReactTestSuite.symbols index 1ee71370dbc..24ff3a1cf3d 100644 --- a/tests/baselines/reference/jsxReactTestSuite.symbols +++ b/tests/baselines/reference/jsxReactTestSuite.symbols @@ -56,9 +56,11 @@ declare var hasOwnProperty:any; >div : Symbol(unknown) {foo}
{bar}
+>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11)) >foo : Symbol(foo, Decl(jsxReactTestSuite.tsx, 7, 11)) >br : Symbol(unknown) >bar : Symbol(bar, Decl(jsxReactTestSuite.tsx, 8, 11)) +>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11))
>br : Symbol(unknown) @@ -68,12 +70,20 @@ declare var hasOwnProperty:any; +>Composite : Symbol(Composite, Decl(jsxReactTestSuite.tsx, 3, 11)) + {this.props.children} ; +>Composite : Symbol(Composite, Decl(jsxReactTestSuite.tsx, 3, 11)) +>Composite : Symbol(Composite, Decl(jsxReactTestSuite.tsx, 3, 11)) + +>Composite2 : Symbol(Composite2, Decl(jsxReactTestSuite.tsx, 4, 11)) + ; +>Composite : Symbol(Composite, Decl(jsxReactTestSuite.tsx, 3, 11)) var x = >x : Symbol(x, Decl(jsxReactTestSuite.tsx, 10, 11), Decl(jsxReactTestSuite.tsx, 35, 3)) @@ -164,6 +174,7 @@ var x = >hasOwnProperty : Symbol(unknown) ; +>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11)) >constructor : Symbol(unknown) ; @@ -171,6 +182,7 @@ var x = ; Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11)) >x : Symbol(x, Decl(jsxReactTestSuite.tsx, 10, 11), Decl(jsxReactTestSuite.tsx, 35, 3)) >y : Symbol(unknown) @@ -178,6 +190,8 @@ var x = >z : Symbol(unknown) Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11)) + {...this.props} sound="moo" />; >sound : Symbol(unknown) @@ -185,6 +199,7 @@ var x = >font-face : Symbol(unknown) ; +>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11)) >x : Symbol(unknown) >y : Symbol(y, Decl(jsxReactTestSuite.tsx, 9, 11)) @@ -192,34 +207,43 @@ var x = >x-component : Symbol(unknown) ; +>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11)) >x : Symbol(x, Decl(jsxReactTestSuite.tsx, 10, 11), Decl(jsxReactTestSuite.tsx, 35, 3)) ; +>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11)) >x : Symbol(x, Decl(jsxReactTestSuite.tsx, 10, 11), Decl(jsxReactTestSuite.tsx, 35, 3)) >y : Symbol(unknown) ; +>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11)) >x : Symbol(x, Decl(jsxReactTestSuite.tsx, 10, 11), Decl(jsxReactTestSuite.tsx, 35, 3)) >y : Symbol(unknown) >z : Symbol(unknown) ; +>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11)) >x : Symbol(unknown) >y : Symbol(y, Decl(jsxReactTestSuite.tsx, 9, 11)) ; +>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11)) >x : Symbol(unknown) >y : Symbol(unknown) >z : Symbol(z, Decl(jsxReactTestSuite.tsx, 11, 11)) >z : Symbol(z, Decl(jsxReactTestSuite.tsx, 11, 11)) +>Child : Symbol(Child, Decl(jsxReactTestSuite.tsx, 5, 11)) +>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11)) Text; +>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11)) >x : Symbol(unknown) >z : Symbol(z, Decl(jsxReactTestSuite.tsx, 11, 11)) >y : Symbol(y, Decl(jsxReactTestSuite.tsx, 113, 27)) >z : Symbol(z, Decl(jsxReactTestSuite.tsx, 11, 11)) >z : Symbol(unknown) +>Component : Symbol(Component, Decl(jsxReactTestSuite.tsx, 2, 11)) diff --git a/tests/baselines/reference/reactNamespaceJSXEmit.symbols b/tests/baselines/reference/reactNamespaceJSXEmit.symbols index a0012cfd07a..3ca5b91e538 100644 --- a/tests/baselines/reference/reactNamespaceJSXEmit.symbols +++ b/tests/baselines/reference/reactNamespaceJSXEmit.symbols @@ -17,6 +17,7 @@ declare var x: any; >data : Symbol(unknown) ; +>Bar : Symbol(Bar, Decl(reactNamespaceJSXEmit.tsx, 3, 11)) >x : Symbol(unknown) >x : Symbol(x, Decl(reactNamespaceJSXEmit.tsx, 4, 11)) @@ -24,9 +25,11 @@ declare var x: any; >x-component : Symbol(unknown) ; +>Bar : Symbol(Bar, Decl(reactNamespaceJSXEmit.tsx, 3, 11)) >x : Symbol(x, Decl(reactNamespaceJSXEmit.tsx, 4, 11)) ; +>Bar : Symbol(Bar, Decl(reactNamespaceJSXEmit.tsx, 3, 11)) >x : Symbol(x, Decl(reactNamespaceJSXEmit.tsx, 4, 11)) >y : Symbol(unknown) diff --git a/tests/baselines/reference/tsxElementResolution19.symbols b/tests/baselines/reference/tsxElementResolution19.symbols index 87c48ccedf0..48aa4f962b6 100644 --- a/tests/baselines/reference/tsxElementResolution19.symbols +++ b/tests/baselines/reference/tsxElementResolution19.symbols @@ -24,5 +24,5 @@ import {MyClass} from './file1'; >MyClass : Symbol(MyClass, Decl(file2.tsx, 3, 8)) ; ->MyClass : Symbol(MyClass, Decl(file1.tsx, 2, 1)) +>MyClass : Symbol(MyClass, Decl(file2.tsx, 3, 8)) diff --git a/tests/baselines/reference/tsxExternalModuleEmit1.symbols b/tests/baselines/reference/tsxExternalModuleEmit1.symbols index 261a9035216..e2d3eee98b0 100644 --- a/tests/baselines/reference/tsxExternalModuleEmit1.symbols +++ b/tests/baselines/reference/tsxExternalModuleEmit1.symbols @@ -25,7 +25,7 @@ export class App extends React.Component { >render : Symbol(App.render, Decl(app.tsx, 5, 52)) return