From f6a3a3fc3dc5aac5d5b1bbec8a64656be6cbda85 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 14 Feb 2017 12:04:39 -0800 Subject: [PATCH 01/65] Use '__this__' property in contextual type to indicate type of 'this' --- src/compiler/checker.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2b059e29d09..1f59d28cc7c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11189,6 +11189,19 @@ namespace ts { return getTypeOfSymbol(thisParameter); } } + if (isObjectLiteralMethod(func)) { + // For methods in an object literal, look for a '__this__' property in the contextual + // type for the object literal. If one exists, remove 'undefined' from the type of that + // property and report it as the contextual type for 'this' in the method. + const objectLiteral = func.parent; + const type = getApparentTypeOfContextualType(objectLiteral); + if (type) { + const propertyType = getTypeOfPropertyOfContextualType(type, "___this__"); + if (propertyType) { + return getNonNullableType(propertyType); + } + } + } } return undefined; } From 8cd6c5d8eb27dc12f3fbc17236271440214d2690 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 16 Feb 2017 17:03:39 -0800 Subject: [PATCH 02/65] Introduce ThisType marker interface --- src/compiler/checker.ts | 53 +++++++++++++++++++++++++++++++---------- src/lib/es5.d.ts | 5 ++++ 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1f59d28cc7c..898b7b4d539 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -197,6 +197,7 @@ namespace ts { let globalNumberType: ObjectType; let globalBooleanType: ObjectType; let globalRegExpType: ObjectType; + let globalThisType: GenericType; let anyArrayType: Type; let autoArrayType: Type; let anyReadonlyArrayType: Type; @@ -5802,6 +5803,11 @@ namespace ts { return getTypeOfGlobalSymbol(getGlobalTypeSymbol(name), arity); } + function getGlobalTypeOrUndefined(name: string, arity = 0): ObjectType { + const symbol = getGlobalSymbol(name, SymbolFlags.Type, /*diagnostic*/ undefined); + return symbol && getTypeOfGlobalSymbol(symbol, arity); + } + /** * Returns a type that is inside a namespace at the global scope, e.g. * getExportedTypeFromNamespace('JSX', 'Element') returns the JSX.Element type @@ -11180,6 +11186,22 @@ namespace ts { } } + function getContainingObjectLiteral(func: FunctionLikeDeclaration) { + return func.kind === SyntaxKind.MethodDeclaration && func.parent.kind === SyntaxKind.ObjectLiteralExpression ? func.parent : + func.kind === SyntaxKind.FunctionExpression && func.parent.kind === SyntaxKind.PropertyAssignment ? func.parent.parent : + undefined; + } + + function getThisTypeArgument(type: Type): Type { + return getObjectFlags(type) & ObjectFlags.Reference && (type).target === globalThisType ? (type).typeArguments[0] : undefined; + } + + function getThisTypeFromContextualType(type: Type): Type { + return applyToContextualType(type, t => { + return t.flags & TypeFlags.Intersection ? forEach((t).types, getThisTypeArgument) : getThisTypeArgument(t); + }); + } + function getContextualThisParameterType(func: FunctionLikeDeclaration): Type { if (isContextSensitiveFunctionOrObjectLiteralMethod(func) && func.kind !== SyntaxKind.ArrowFunction) { const contextualSignature = getContextualSignature(func); @@ -11189,17 +11211,24 @@ namespace ts { return getTypeOfSymbol(thisParameter); } } - if (isObjectLiteralMethod(func)) { - // For methods in an object literal, look for a '__this__' property in the contextual - // type for the object literal. If one exists, remove 'undefined' from the type of that - // property and report it as the contextual type for 'this' in the method. - const objectLiteral = func.parent; - const type = getApparentTypeOfContextualType(objectLiteral); - if (type) { - const propertyType = getTypeOfPropertyOfContextualType(type, "___this__"); - if (propertyType) { - return getNonNullableType(propertyType); + const containingLiteral = getContainingObjectLiteral(func); + if (containingLiteral) { + // We have an object literal method. Check if the containing object literal has a contextual type + // and if that contextual type is or includes a ThisType. If so, T is the contextual type for + // 'this'. We continue looking in any directly enclosing object literals. + let objectLiteral = containingLiteral; + while (true) { + const type = getApparentTypeOfContextualType(objectLiteral); + if (type) { + const thisType = getThisTypeFromContextualType(type); + if (thisType) { + return thisType; + } } + if (objectLiteral.parent.kind !== SyntaxKind.PropertyAssignment) { + break; + } + objectLiteral = objectLiteral.parent.parent; } } } @@ -21175,9 +21204,9 @@ namespace ts { anyArrayType = createArrayType(anyType); autoArrayType = createArrayType(autoType); - const symbol = getGlobalSymbol("ReadonlyArray", SymbolFlags.Type, /*diagnostic*/ undefined); - globalReadonlyArrayType = symbol && getTypeOfGlobalSymbol(symbol, /*arity*/ 1); + globalReadonlyArrayType = getGlobalTypeOrUndefined("ReadonlyArray", /*arity*/ 1); anyReadonlyArrayType = globalReadonlyArrayType ? createTypeFromGenericGlobalType(globalReadonlyArrayType, [anyType]) : anyArrayType; + globalThisType = getGlobalTypeOrUndefined("ThisType", /*arity*/ 1); } function checkExternalEmitHelpers(location: Node, helpers: ExternalEmitHelpers) { diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index 038d0344fda..6ff9b8f533a 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -1384,6 +1384,11 @@ type Record = { [P in K]: T; } +/** + * Marker for contextual 'this' type + */ +interface ThisType { } + /** * Represents a raw buffer of binary data, which is used to store data for the * different typed arrays. ArrayBuffers cannot be read from or written to directly, From 2ca6164fea89ca344b04ee775a472564ae836511 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 16 Feb 2017 17:04:30 -0800 Subject: [PATCH 03/65] Default contextual 'this' type is containing object literal --- src/compiler/checker.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 898b7b4d539..3949a65eea8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11230,6 +11230,9 @@ namespace ts { } objectLiteral = objectLiteral.parent.parent; } + // There was no contextual ThisType for the containing object literal, so the contextual type + // for 'this' is the type of the object literal itself. + return checkExpressionCached(containingLiteral); } } return undefined; From e512376b0c5ae25d0e66b4c92bc6618cbd262c95 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 16 Feb 2017 17:42:22 -0800 Subject: [PATCH 04/65] Update tests --- tests/cases/compiler/noImplicitThisObjectLiterals.ts | 10 ---------- .../typePredicates/declarationEmitThisPredicates02.ts | 2 +- .../declarationEmitThisPredicatesWithPrivateName02.ts | 2 +- .../expressions/thisKeyword/thisInObjectLiterals.ts | 3 ++- .../conformance/types/thisType/thisTypeInFunctions2.ts | 7 +++---- 5 files changed, 7 insertions(+), 17 deletions(-) delete mode 100644 tests/cases/compiler/noImplicitThisObjectLiterals.ts diff --git a/tests/cases/compiler/noImplicitThisObjectLiterals.ts b/tests/cases/compiler/noImplicitThisObjectLiterals.ts deleted file mode 100644 index abd5d9dcfba..00000000000 --- a/tests/cases/compiler/noImplicitThisObjectLiterals.ts +++ /dev/null @@ -1,10 +0,0 @@ -// @noImplicitThis: true -let o = { - d: this, // error, this: any - m() { - return this.d.length; // error, this: any - }, - f: function() { - return this.d.length; // error, this: any - } -} diff --git a/tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicates02.ts b/tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicates02.ts index 02f2a798831..c17b26f423c 100644 --- a/tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicates02.ts +++ b/tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicates02.ts @@ -9,7 +9,7 @@ export interface Foo { export const obj = { m(): this is Foo { - let dis = this as Foo; + let dis = this as {} as Foo; return dis.a != null && dis.b != null && dis.c != null; } } \ No newline at end of file diff --git a/tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicatesWithPrivateName02.ts b/tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicatesWithPrivateName02.ts index c238bb16ec8..94e657db9f3 100644 --- a/tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicatesWithPrivateName02.ts +++ b/tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicatesWithPrivateName02.ts @@ -9,7 +9,7 @@ interface Foo { export const obj = { m(): this is Foo { - let dis = this as Foo; + let dis = this as {} as Foo; return dis.a != null && dis.b != null && dis.c != null; } } \ 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 ddfbb790980..6219586b6e5 100644 --- a/tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts +++ b/tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts @@ -2,9 +2,10 @@ class MyClass { t: number; fn() { + type ContainingThis = this; //type of 'this' in an object literal is the containing scope's this var t = { x: this, y: this.t }; - var t: { x: MyClass; y: number }; + var t: { x: ContainingThis; y: number }; } } diff --git a/tests/cases/conformance/types/thisType/thisTypeInFunctions2.ts b/tests/cases/conformance/types/thisType/thisTypeInFunctions2.ts index a574c7a07e9..0d1581633c3 100644 --- a/tests/cases/conformance/types/thisType/thisTypeInFunctions2.ts +++ b/tests/cases/conformance/types/thisType/thisTypeInFunctions2.ts @@ -32,15 +32,14 @@ extend1({ }); extend2({ init() { - this // this: any because the contextual signature of init doesn't specify this' type + this // this: containing object literal type this.mine - this.willDestroy + //this.willDestroy }, mine: 13, foo() { - this // this: any because of the string indexer + this // this: containing object literal type this.mine - this.willDestroy } }); From d7e153d25228c9c8527dd9d38b464c53729b959d Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 16 Feb 2017 17:47:58 -0800 Subject: [PATCH 05/65] Accept new baselines --- tests/baselines/reference/castTest.symbols | 6 ++ tests/baselines/reference/castTest.types | 16 +-- .../commentsOnObjectLiteral2.errors.txt | 5 +- ...declarationEmitThisPredicates02.errors.txt | 2 +- .../declarationEmitThisPredicates02.js | 2 +- ...ThisPredicatesWithPrivateName02.errors.txt | 2 +- ...tionEmitThisPredicatesWithPrivateName02.js | 2 +- .../reference/fatarrowfunctions.symbols | 5 + .../reference/fatarrowfunctions.types | 12 +-- .../fatarrowfunctionsInFunctions.symbols | 5 + .../fatarrowfunctionsInFunctions.types | 16 +-- .../reference/fixSignatureCaching.errors.txt | 98 ++++++++++++++++++- .../looseThisTypeInFunctions.errors.txt | 5 +- .../baselines/reference/objectSpread.symbols | 3 + tests/baselines/reference/objectSpread.types | 12 +-- .../baselines/reference/selfInLambdas.symbols | 7 ++ tests/baselines/reference/selfInLambdas.types | 16 +-- .../baselines/reference/thisBinding2.symbols | 3 + tests/baselines/reference/thisBinding2.types | 8 +- .../reference/thisInObjectLiterals.errors.txt | 9 +- .../reference/thisInObjectLiterals.js | 3 +- .../thisInPropertyBoundDeclarations.symbols | 2 + .../thisInPropertyBoundDeclarations.types | 12 +-- .../reference/thisTypeInFunctions2.js | 14 ++- .../reference/thisTypeInFunctions2.symbols | 29 ++++-- .../reference/thisTypeInFunctions2.types | 49 ++++------ .../thisTypeInObjectLiterals.symbols | 24 +++++ .../reference/thisTypeInObjectLiterals.types | 78 +++++++-------- .../throwInEnclosingStatements.symbols | 1 + .../throwInEnclosingStatements.types | 2 +- .../reference/underscoreTest1.symbols | 6 ++ .../baselines/reference/underscoreTest1.types | 12 +-- 32 files changed, 317 insertions(+), 149 deletions(-) diff --git a/tests/baselines/reference/castTest.symbols b/tests/baselines/reference/castTest.symbols index 944cc8238e6..706f75a1028 100644 --- a/tests/baselines/reference/castTest.symbols +++ b/tests/baselines/reference/castTest.symbols @@ -71,7 +71,13 @@ var p_cast = ({ return new Point(this.x + dx, this.y + dy); >Point : Symbol(Point, Decl(castTest.ts, 11, 37)) +>this.x : Symbol(x, Decl(castTest.ts, 22, 23)) +>this : Symbol(__object, Decl(castTest.ts, 22, 22)) +>x : Symbol(x, Decl(castTest.ts, 22, 23)) >dx : Symbol(dx, Decl(castTest.ts, 25, 18)) +>this.y : Symbol(y, Decl(castTest.ts, 23, 9)) +>this : Symbol(__object, Decl(castTest.ts, 22, 22)) +>y : Symbol(y, Decl(castTest.ts, 23, 9)) >dy : Symbol(dy, Decl(castTest.ts, 25, 21)) }, diff --git a/tests/baselines/reference/castTest.types b/tests/baselines/reference/castTest.types index 666b2ccf78e..acdc58d0b25 100644 --- a/tests/baselines/reference/castTest.types +++ b/tests/baselines/reference/castTest.types @@ -91,15 +91,15 @@ var p_cast = ({ return new Point(this.x + dx, this.y + dy); >new Point(this.x + dx, this.y + dy) : Point >Point : typeof Point ->this.x + dx : any ->this.x : any ->this : any ->x : any +>this.x + dx : number +>this.x : number +>this : { x: number; y: number; add: (dx: number, dy: number) => Point; mult: (p: Point) => Point; } +>x : number >dx : number ->this.y + dy : any ->this.y : any ->this : any ->y : any +>this.y + dy : number +>this.y : number +>this : { x: number; y: number; add: (dx: number, dy: number) => Point; mult: (p: Point) => Point; } +>y : number >dy : number }, diff --git a/tests/baselines/reference/commentsOnObjectLiteral2.errors.txt b/tests/baselines/reference/commentsOnObjectLiteral2.errors.txt index 2a2394ced48..3748d0387b6 100644 --- a/tests/baselines/reference/commentsOnObjectLiteral2.errors.txt +++ b/tests/baselines/reference/commentsOnObjectLiteral2.errors.txt @@ -1,7 +1,8 @@ tests/cases/compiler/commentsOnObjectLiteral2.ts(1,14): error TS2304: Cannot find name 'makeClass'. +tests/cases/compiler/commentsOnObjectLiteral2.ts(9,17): error TS2339: Property 'name' does not exist on type '{ initialize: (name: any) => void; }'. -==== tests/cases/compiler/commentsOnObjectLiteral2.ts (1 errors) ==== +==== tests/cases/compiler/commentsOnObjectLiteral2.ts (2 errors) ==== var Person = makeClass( ~~~~~~~~~ !!! error TS2304: Cannot find name 'makeClass'. @@ -13,6 +14,8 @@ tests/cases/compiler/commentsOnObjectLiteral2.ts(1,14): error TS2304: Cannot fin */ initialize: function(name) { this.name = name; + ~~~~ +!!! error TS2339: Property 'name' does not exist on type '{ initialize: (name: any) => void; }'. } /* trailing comment 1*/, } ); \ No newline at end of file diff --git a/tests/baselines/reference/declarationEmitThisPredicates02.errors.txt b/tests/baselines/reference/declarationEmitThisPredicates02.errors.txt index 4d95cf01136..e4f95d98803 100644 --- a/tests/baselines/reference/declarationEmitThisPredicates02.errors.txt +++ b/tests/baselines/reference/declarationEmitThisPredicates02.errors.txt @@ -13,7 +13,7 @@ tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredic m(): this is Foo { ~~~~ !!! error TS2526: A 'this' type is available only in a non-static member of a class or interface. - let dis = this as Foo; + let dis = this as {} as Foo; return dis.a != null && dis.b != null && dis.c != null; } } \ No newline at end of file diff --git a/tests/baselines/reference/declarationEmitThisPredicates02.js b/tests/baselines/reference/declarationEmitThisPredicates02.js index 0e7c99df1f3..46deae372ca 100644 --- a/tests/baselines/reference/declarationEmitThisPredicates02.js +++ b/tests/baselines/reference/declarationEmitThisPredicates02.js @@ -8,7 +8,7 @@ export interface Foo { export const obj = { m(): this is Foo { - let dis = this as Foo; + let dis = this as {} as Foo; return dis.a != null && dis.b != null && dis.c != null; } } diff --git a/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.errors.txt b/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.errors.txt index 86c0f478133..bd2f4700fa2 100644 --- a/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.errors.txt +++ b/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.errors.txt @@ -16,7 +16,7 @@ tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredic m(): this is Foo { ~~~~ !!! error TS2526: A 'this' type is available only in a non-static member of a class or interface. - let dis = this as Foo; + let dis = this as {} as Foo; return dis.a != null && dis.b != null && dis.c != null; } } \ No newline at end of file diff --git a/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.js b/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.js index 7ec7ba5dec8..fe1a95db5e3 100644 --- a/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.js +++ b/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.js @@ -8,7 +8,7 @@ interface Foo { export const obj = { m(): this is Foo { - let dis = this as Foo; + let dis = this as {} as Foo; return dis.a != null && dis.b != null && dis.c != null; } } diff --git a/tests/baselines/reference/fatarrowfunctions.symbols b/tests/baselines/reference/fatarrowfunctions.symbols index 6ed865b0914..1e5fb4f3178 100644 --- a/tests/baselines/reference/fatarrowfunctions.symbols +++ b/tests/baselines/reference/fatarrowfunctions.symbols @@ -163,6 +163,11 @@ var messenger = { setTimeout(() => { this.message.toString(); }, 3000); >setTimeout : Symbol(setTimeout, Decl(fatarrowfunctions.ts, 34, 1)) +>this.message.toString : Symbol(String.toString, Decl(lib.d.ts, --, --)) +>this.message : Symbol(message, Decl(fatarrowfunctions.ts, 38, 17)) +>this : Symbol(__object, Decl(fatarrowfunctions.ts, 38, 15)) +>message : Symbol(message, Decl(fatarrowfunctions.ts, 38, 17)) +>toString : Symbol(String.toString, Decl(lib.d.ts, --, --)) } }; diff --git a/tests/baselines/reference/fatarrowfunctions.types b/tests/baselines/reference/fatarrowfunctions.types index 304c341c916..1114ae365cb 100644 --- a/tests/baselines/reference/fatarrowfunctions.types +++ b/tests/baselines/reference/fatarrowfunctions.types @@ -234,12 +234,12 @@ var messenger = { >setTimeout(() => { this.message.toString(); }, 3000) : number >setTimeout : (expression: any, msec?: number, language?: any) => number >() => { this.message.toString(); } : () => void ->this.message.toString() : any ->this.message.toString : any ->this.message : any ->this : any ->message : any ->toString : any +>this.message.toString() : string +>this.message.toString : () => string +>this.message : string +>this : { message: string; start: () => void; } +>message : string +>toString : () => string >3000 : 3000 } }; diff --git a/tests/baselines/reference/fatarrowfunctionsInFunctions.symbols b/tests/baselines/reference/fatarrowfunctionsInFunctions.symbols index 0a86affc215..f1123f4aa96 100644 --- a/tests/baselines/reference/fatarrowfunctionsInFunctions.symbols +++ b/tests/baselines/reference/fatarrowfunctionsInFunctions.symbols @@ -16,12 +16,17 @@ var messenger = { var _self = this; >_self : Symbol(_self, Decl(fatarrowfunctionsInFunctions.ts, 5, 11)) +>this : Symbol(__object, Decl(fatarrowfunctionsInFunctions.ts, 2, 15)) setTimeout(function() { >setTimeout : Symbol(setTimeout, Decl(fatarrowfunctionsInFunctions.ts, 0, 0)) _self.message.toString(); +>_self.message.toString : Symbol(String.toString, Decl(lib.d.ts, --, --)) +>_self.message : Symbol(message, Decl(fatarrowfunctionsInFunctions.ts, 2, 17)) >_self : Symbol(_self, Decl(fatarrowfunctionsInFunctions.ts, 5, 11)) +>message : Symbol(message, Decl(fatarrowfunctionsInFunctions.ts, 2, 17)) +>toString : Symbol(String.toString, Decl(lib.d.ts, --, --)) }, 3000); } diff --git a/tests/baselines/reference/fatarrowfunctionsInFunctions.types b/tests/baselines/reference/fatarrowfunctionsInFunctions.types index 8b9bd7ccd7a..88807f2a37b 100644 --- a/tests/baselines/reference/fatarrowfunctionsInFunctions.types +++ b/tests/baselines/reference/fatarrowfunctionsInFunctions.types @@ -18,8 +18,8 @@ var messenger = { >function() { var _self = this; setTimeout(function() { _self.message.toString(); }, 3000); } : () => void var _self = this; ->_self : any ->this : any +>_self : { message: string; start: () => void; } +>this : { message: string; start: () => void; } setTimeout(function() { >setTimeout(function() { _self.message.toString(); }, 3000) : number @@ -27,12 +27,12 @@ var messenger = { >function() { _self.message.toString(); } : () => void _self.message.toString(); ->_self.message.toString() : any ->_self.message.toString : any ->_self.message : any ->_self : any ->message : any ->toString : any +>_self.message.toString() : string +>_self.message.toString : () => string +>_self.message : string +>_self : { message: string; start: () => void; } +>message : string +>toString : () => string }, 3000); >3000 : 3000 diff --git a/tests/baselines/reference/fixSignatureCaching.errors.txt b/tests/baselines/reference/fixSignatureCaching.errors.txt index 7a5c43c966e..284a0d13926 100644 --- a/tests/baselines/reference/fixSignatureCaching.errors.txt +++ b/tests/baselines/reference/fixSignatureCaching.errors.txt @@ -41,19 +41,51 @@ tests/cases/conformance/fixSignatureCaching.ts(639,38): error TS2304: Cannot fin tests/cases/conformance/fixSignatureCaching.ts(640,13): error TS2304: Cannot find name 'window'. tests/cases/conformance/fixSignatureCaching.ts(641,13): error TS2304: Cannot find name 'window'. tests/cases/conformance/fixSignatureCaching.ts(704,18): error TS2339: Property 'prepareDetectionCache' does not exist on type '{}'. +tests/cases/conformance/fixSignatureCaching.ts(704,45): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. +tests/cases/conformance/fixSignatureCaching.ts(704,58): error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. +tests/cases/conformance/fixSignatureCaching.ts(704,67): error TS2339: Property 'maxPhoneWidth' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. +tests/cases/conformance/fixSignatureCaching.ts(705,25): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. tests/cases/conformance/fixSignatureCaching.ts(734,18): error TS2339: Property 'prepareDetectionCache' does not exist on type '{}'. +tests/cases/conformance/fixSignatureCaching.ts(734,45): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. +tests/cases/conformance/fixSignatureCaching.ts(734,58): error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. +tests/cases/conformance/fixSignatureCaching.ts(734,67): error TS2339: Property 'maxPhoneWidth' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. +tests/cases/conformance/fixSignatureCaching.ts(735,25): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. tests/cases/conformance/fixSignatureCaching.ts(783,18): error TS2339: Property 'prepareDetectionCache' does not exist on type '{}'. +tests/cases/conformance/fixSignatureCaching.ts(783,45): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. +tests/cases/conformance/fixSignatureCaching.ts(783,58): error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. +tests/cases/conformance/fixSignatureCaching.ts(783,67): error TS2339: Property 'maxPhoneWidth' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. +tests/cases/conformance/fixSignatureCaching.ts(784,25): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. +tests/cases/conformance/fixSignatureCaching.ts(804,22): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. +tests/cases/conformance/fixSignatureCaching.ts(805,22): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. tests/cases/conformance/fixSignatureCaching.ts(805,46): error TS2339: Property 'findMatch' does not exist on type '{}'. tests/cases/conformance/fixSignatureCaching.ts(805,61): error TS2339: Property 'mobileDetectRules' does not exist on type '{}'. +tests/cases/conformance/fixSignatureCaching.ts(805,89): error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. +tests/cases/conformance/fixSignatureCaching.ts(807,25): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. +tests/cases/conformance/fixSignatureCaching.ts(827,22): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. +tests/cases/conformance/fixSignatureCaching.ts(828,22): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. tests/cases/conformance/fixSignatureCaching.ts(828,47): error TS2339: Property 'findMatches' does not exist on type '{}'. tests/cases/conformance/fixSignatureCaching.ts(828,64): error TS2339: Property 'mobileDetectRules' does not exist on type '{}'. +tests/cases/conformance/fixSignatureCaching.ts(828,92): error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. +tests/cases/conformance/fixSignatureCaching.ts(830,25): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. +tests/cases/conformance/fixSignatureCaching.ts(844,22): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. +tests/cases/conformance/fixSignatureCaching.ts(845,22): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. tests/cases/conformance/fixSignatureCaching.ts(845,39): error TS2339: Property 'detectOS' does not exist on type '{}'. +tests/cases/conformance/fixSignatureCaching.ts(845,53): error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. +tests/cases/conformance/fixSignatureCaching.ts(847,25): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. tests/cases/conformance/fixSignatureCaching.ts(869,25): error TS2339: Property 'getVersion' does not exist on type '{}'. +tests/cases/conformance/fixSignatureCaching.ts(869,46): error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. tests/cases/conformance/fixSignatureCaching.ts(890,25): error TS2339: Property 'getVersionStr' does not exist on type '{}'. +tests/cases/conformance/fixSignatureCaching.ts(890,49): error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. tests/cases/conformance/fixSignatureCaching.ts(912,36): error TS2339: Property 'findMatches' does not exist on type '{}'. tests/cases/conformance/fixSignatureCaching.ts(912,53): error TS2339: Property 'mobileDetectRules' does not exist on type '{}'. +tests/cases/conformance/fixSignatureCaching.ts(912,83): error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. +tests/cases/conformance/fixSignatureCaching.ts(927,38): error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. tests/cases/conformance/fixSignatureCaching.ts(941,33): error TS2339: Property 'isPhoneSized' does not exist on type '(userAgent: any, maxPhoneWidth: any) => void'. +tests/cases/conformance/fixSignatureCaching.ts(941,68): error TS2339: Property 'maxPhoneWidth' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. +tests/cases/conformance/fixSignatureCaching.ts(951,22): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. +tests/cases/conformance/fixSignatureCaching.ts(952,22): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. tests/cases/conformance/fixSignatureCaching.ts(952,42): error TS2339: Property 'mobileGrade' does not exist on type '{}'. +tests/cases/conformance/fixSignatureCaching.ts(954,25): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. tests/cases/conformance/fixSignatureCaching.ts(959,16): error TS2304: Cannot find name 'window'. tests/cases/conformance/fixSignatureCaching.ts(959,42): error TS2304: Cannot find name 'window'. tests/cases/conformance/fixSignatureCaching.ts(960,22): error TS2339: Property 'isPhoneSized' does not exist on type '(userAgent: any, maxPhoneWidth: any) => void'. @@ -71,7 +103,7 @@ tests/cases/conformance/fixSignatureCaching.ts(979,23): error TS2304: Cannot fin tests/cases/conformance/fixSignatureCaching.ts(980,37): error TS2304: Cannot find name 'window'. -==== tests/cases/conformance/fixSignatureCaching.ts (71 errors) ==== +==== tests/cases/conformance/fixSignatureCaching.ts (103 errors) ==== // Repro from #10697 (function (define, undefined) { @@ -862,7 +894,15 @@ tests/cases/conformance/fixSignatureCaching.ts(980,37): error TS2304: Cannot fin impl.prepareDetectionCache(this._cache, this.ua, this.maxPhoneWidth); ~~~~~~~~~~~~~~~~~~~~~ !!! error TS2339: Property 'prepareDetectionCache' does not exist on type '{}'. + ~~~~~~ +!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. + ~~ +!!! error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. + ~~~~~~~~~~~~~ +!!! error TS2339: Property 'maxPhoneWidth' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. return this._cache.mobile; + ~~~~~~ +!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. }, /** @@ -894,7 +934,15 @@ tests/cases/conformance/fixSignatureCaching.ts(980,37): error TS2304: Cannot fin impl.prepareDetectionCache(this._cache, this.ua, this.maxPhoneWidth); ~~~~~~~~~~~~~~~~~~~~~ !!! error TS2339: Property 'prepareDetectionCache' does not exist on type '{}'. + ~~~~~~ +!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. + ~~ +!!! error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. + ~~~~~~~~~~~~~ +!!! error TS2339: Property 'maxPhoneWidth' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. return this._cache.phone; + ~~~~~~ +!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. }, /** @@ -945,7 +993,15 @@ tests/cases/conformance/fixSignatureCaching.ts(980,37): error TS2304: Cannot fin impl.prepareDetectionCache(this._cache, this.ua, this.maxPhoneWidth); ~~~~~~~~~~~~~~~~~~~~~ !!! error TS2339: Property 'prepareDetectionCache' does not exist on type '{}'. + ~~~~~~ +!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. + ~~ +!!! error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. + ~~~~~~~~~~~~~ +!!! error TS2339: Property 'maxPhoneWidth' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. return this._cache.tablet; + ~~~~~~ +!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. }, /** @@ -966,13 +1022,21 @@ tests/cases/conformance/fixSignatureCaching.ts(980,37): error TS2304: Cannot fin */ userAgent: function () { if (this._cache.userAgent === undefined) { + ~~~~~~ +!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. this._cache.userAgent = impl.findMatch(impl.mobileDetectRules.uas, this.ua); + ~~~~~~ +!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. ~~~~~~~~~ !!! error TS2339: Property 'findMatch' does not exist on type '{}'. ~~~~~~~~~~~~~~~~~ !!! error TS2339: Property 'mobileDetectRules' does not exist on type '{}'. + ~~ +!!! error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. } return this._cache.userAgent; + ~~~~~~ +!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. }, /** @@ -993,13 +1057,21 @@ tests/cases/conformance/fixSignatureCaching.ts(980,37): error TS2304: Cannot fin */ userAgents: function () { if (this._cache.userAgents === undefined) { + ~~~~~~ +!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. this._cache.userAgents = impl.findMatches(impl.mobileDetectRules.uas, this.ua); + ~~~~~~ +!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. ~~~~~~~~~~~ !!! error TS2339: Property 'findMatches' does not exist on type '{}'. ~~~~~~~~~~~~~~~~~ !!! error TS2339: Property 'mobileDetectRules' does not exist on type '{}'. + ~~ +!!! error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. } return this._cache.userAgents; + ~~~~~~ +!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. }, /** @@ -1014,11 +1086,19 @@ tests/cases/conformance/fixSignatureCaching.ts(980,37): error TS2304: Cannot fin */ os: function () { if (this._cache.os === undefined) { + ~~~~~~ +!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. this._cache.os = impl.detectOS(this.ua); + ~~~~~~ +!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. ~~~~~~~~ !!! error TS2339: Property 'detectOS' does not exist on type '{}'. + ~~ +!!! error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. } return this._cache.os; + ~~~~~~ +!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. }, /** @@ -1043,6 +1123,8 @@ tests/cases/conformance/fixSignatureCaching.ts(980,37): error TS2304: Cannot fin return impl.getVersion(key, this.ua); ~~~~~~~~~~ !!! error TS2339: Property 'getVersion' does not exist on type '{}'. + ~~ +!!! error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. }, /** @@ -1066,6 +1148,8 @@ tests/cases/conformance/fixSignatureCaching.ts(980,37): error TS2304: Cannot fin return impl.getVersionStr(key, this.ua); ~~~~~~~~~~~~~ !!! error TS2339: Property 'getVersionStr' does not exist on type '{}'. + ~~ +!!! error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. }, /** @@ -1092,6 +1176,8 @@ tests/cases/conformance/fixSignatureCaching.ts(980,37): error TS2304: Cannot fin !!! error TS2339: Property 'findMatches' does not exist on type '{}'. ~~~~~~~~~~~~~~~~~ !!! error TS2339: Property 'mobileDetectRules' does not exist on type '{}'. + ~~ +!!! error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. }, /** @@ -1107,6 +1193,8 @@ tests/cases/conformance/fixSignatureCaching.ts(980,37): error TS2304: Cannot fin pattern = new RegExp(pattern, 'i'); } return pattern.test(this.ua); + ~~ +!!! error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. }, /** @@ -1123,6 +1211,8 @@ tests/cases/conformance/fixSignatureCaching.ts(980,37): error TS2304: Cannot fin return MobileDetect.isPhoneSized(maxPhoneWidth || this.maxPhoneWidth); ~~~~~~~~~~~~ !!! error TS2339: Property 'isPhoneSized' does not exist on type '(userAgent: any, maxPhoneWidth: any) => void'. + ~~~~~~~~~~~~~ +!!! error TS2339: Property 'maxPhoneWidth' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. }, /** @@ -1133,11 +1223,17 @@ tests/cases/conformance/fixSignatureCaching.ts(980,37): error TS2304: Cannot fin */ mobileGrade: function () { if (this._cache.grade === undefined) { + ~~~~~~ +!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. this._cache.grade = impl.mobileGrade(this); + ~~~~~~ +!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. ~~~~~~~~~~~ !!! error TS2339: Property 'mobileGrade' does not exist on type '{}'. } return this._cache.grade; + ~~~~~~ +!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. } }; diff --git a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt index bf76c9c9641..7e12a714406 100644 --- a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt +++ b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt @@ -1,12 +1,13 @@ 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'. The 'this' types of each signature are incompatible. Type 'void' is not assignable to type 'C'. +tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(25,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 TS2684: The 'this' context of type 'void' is not assignable to method's 'this' of type 'I'. 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 (4 errors) ==== +==== tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts (5 errors) ==== interface I { n: number; explicitThis(this: this, m: number): number; @@ -36,6 +37,8 @@ tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(46,20): error n: 101, explicitThis: function (m: number) { return m + this.n.length; // error, 'length' does not exist on 'number' + ~~~~~~ +!!! error TS2339: Property 'length' does not exist on type 'number'. }, implicitThis(m: number): number { return m; } }; diff --git a/tests/baselines/reference/objectSpread.symbols b/tests/baselines/reference/objectSpread.symbols index 1ec2520e166..3487f757aeb 100644 --- a/tests/baselines/reference/objectSpread.symbols +++ b/tests/baselines/reference/objectSpread.symbols @@ -200,6 +200,9 @@ let cplus: { p: number, plus(): void } = { ...c, plus() { return this.p + 1; } } >plus : Symbol(plus, Decl(objectSpread.ts, 49, 23)) >c : Symbol(c, Decl(objectSpread.ts, 45, 3)) >plus : Symbol(plus, Decl(objectSpread.ts, 49, 48)) +>this.p : Symbol(C.p, Decl(objectSpread.ts, 44, 9)) +>this : Symbol(__object, Decl(objectSpread.ts, 49, 40)) +>p : Symbol(C.p, Decl(objectSpread.ts, 44, 9)) cplus.plus(); >cplus.plus : Symbol(plus, Decl(objectSpread.ts, 49, 23)) diff --git a/tests/baselines/reference/objectSpread.types b/tests/baselines/reference/objectSpread.types index 950dab43465..b6ad1d13ae4 100644 --- a/tests/baselines/reference/objectSpread.types +++ b/tests/baselines/reference/objectSpread.types @@ -263,13 +263,13 @@ let cplus: { p: number, plus(): void } = { ...c, plus() { return this.p + 1; } } >cplus : { p: number; plus(): void; } >p : number >plus : () => void ->{ ...c, plus() { return this.p + 1; } } : { plus(): any; p: number; } +>{ ...c, plus() { return this.p + 1; } } : { plus(): number; p: number; } >c : C ->plus : () => any ->this.p + 1 : any ->this.p : any ->this : any ->p : any +>plus : () => number +>this.p + 1 : number +>this.p : number +>this : { plus(): number; p: number; } +>p : number >1 : 1 cplus.plus(); diff --git a/tests/baselines/reference/selfInLambdas.symbols b/tests/baselines/reference/selfInLambdas.symbols index edcc03b6bf6..6f91adefcc1 100644 --- a/tests/baselines/reference/selfInLambdas.symbols +++ b/tests/baselines/reference/selfInLambdas.symbols @@ -37,8 +37,15 @@ var o = { >onmousemove : Symbol(Window.onmousemove, Decl(selfInLambdas.ts, 6, 18)) this.counter++ +>this.counter : Symbol(counter, Decl(selfInLambdas.ts, 10, 9)) +>this : Symbol(__object, Decl(selfInLambdas.ts, 10, 7)) +>counter : Symbol(counter, Decl(selfInLambdas.ts, 10, 9)) + var f = () => this.counter; >f : Symbol(f, Decl(selfInLambdas.ts, 18, 15)) +>this.counter : Symbol(counter, Decl(selfInLambdas.ts, 10, 9)) +>this : Symbol(__object, Decl(selfInLambdas.ts, 10, 7)) +>counter : Symbol(counter, Decl(selfInLambdas.ts, 10, 9)) } diff --git a/tests/baselines/reference/selfInLambdas.types b/tests/baselines/reference/selfInLambdas.types index 614ebc16e68..a26e1e0bf28 100644 --- a/tests/baselines/reference/selfInLambdas.types +++ b/tests/baselines/reference/selfInLambdas.types @@ -43,16 +43,16 @@ var o = { this.counter++ >this.counter++ : number ->this.counter : any ->this : any ->counter : any +>this.counter : number +>this : { counter: number; start: () => void; } +>counter : number var f = () => this.counter; ->f : () => any ->() => this.counter : () => any ->this.counter : any ->this : any ->counter : any +>f : () => number +>() => this.counter : () => number +>this.counter : number +>this : { counter: number; start: () => void; } +>counter : number } diff --git a/tests/baselines/reference/thisBinding2.symbols b/tests/baselines/reference/thisBinding2.symbols index cdef9b60b3e..507b7e48419 100644 --- a/tests/baselines/reference/thisBinding2.symbols +++ b/tests/baselines/reference/thisBinding2.symbols @@ -50,6 +50,9 @@ var messenger = { return setTimeout(() => { var x = this.message; }, 3000); >setTimeout : Symbol(setTimeout, Decl(thisBinding2.ts, 12, 1)) >x : Symbol(x, Decl(thisBinding2.ts, 17, 37)) +>this.message : Symbol(message, Decl(thisBinding2.ts, 14, 17)) +>this : Symbol(__object, Decl(thisBinding2.ts, 14, 15)) +>message : Symbol(message, Decl(thisBinding2.ts, 14, 17)) } }; diff --git a/tests/baselines/reference/thisBinding2.types b/tests/baselines/reference/thisBinding2.types index dbd9f83c741..4889e6d3b33 100644 --- a/tests/baselines/reference/thisBinding2.types +++ b/tests/baselines/reference/thisBinding2.types @@ -67,10 +67,10 @@ var messenger = { >setTimeout(() => { var x = this.message; }, 3000) : number >setTimeout : (expression: any, msec?: number, language?: any) => number >() => { var x = this.message; } : () => void ->x : any ->this.message : any ->this : any ->message : any +>x : string +>this.message : string +>this : { message: string; start: () => number; } +>message : string >3000 : 3000 } }; diff --git a/tests/baselines/reference/thisInObjectLiterals.errors.txt b/tests/baselines/reference/thisInObjectLiterals.errors.txt index e89980dc244..3da8430802d 100644 --- a/tests/baselines/reference/thisInObjectLiterals.errors.txt +++ b/tests/baselines/reference/thisInObjectLiterals.errors.txt @@ -1,4 +1,4 @@ -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(15,21): error TS2339: Property 'spaaace' does not exist on type '{ f(): any; }'. ==== tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts (1 errors) ==== @@ -6,11 +6,10 @@ tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts(7,13): e t: number; fn() { + type ContainingThis = this; //type of 'this' in an object literal is the containing scope's this var t = { x: this, y: this.t }; - var t: { x: MyClass; y: number }; - ~ -!!! 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; }'. + var t: { x: ContainingThis; y: number }; } } @@ -18,6 +17,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/thisInObjectLiterals.js b/tests/baselines/reference/thisInObjectLiterals.js index 6c8380060a7..6331f12105d 100644 --- a/tests/baselines/reference/thisInObjectLiterals.js +++ b/tests/baselines/reference/thisInObjectLiterals.js @@ -3,9 +3,10 @@ class MyClass { t: number; fn() { + type ContainingThis = this; //type of 'this' in an object literal is the containing scope's this var t = { x: this, y: this.t }; - var t: { x: MyClass; y: number }; + var t: { x: ContainingThis; y: number }; } } diff --git a/tests/baselines/reference/thisInPropertyBoundDeclarations.symbols b/tests/baselines/reference/thisInPropertyBoundDeclarations.symbols index 12d3b2db31e..6afdd73f77f 100644 --- a/tests/baselines/reference/thisInPropertyBoundDeclarations.symbols +++ b/tests/baselines/reference/thisInPropertyBoundDeclarations.symbols @@ -70,6 +70,7 @@ class A { a: function() { return this; }, >a : Symbol(a, Decl(thisInPropertyBoundDeclarations.ts, 33, 13)) +>this : Symbol(__object, Decl(thisInPropertyBoundDeclarations.ts, 33, 11)) }; @@ -79,6 +80,7 @@ class A { return { a: function() { return this; }, >a : Symbol(a, Decl(thisInPropertyBoundDeclarations.ts, 38, 16)) +>this : Symbol(__object, Decl(thisInPropertyBoundDeclarations.ts, 38, 14)) }; }; diff --git a/tests/baselines/reference/thisInPropertyBoundDeclarations.types b/tests/baselines/reference/thisInPropertyBoundDeclarations.types index b783c5c1b5f..7c2b28bfb3e 100644 --- a/tests/baselines/reference/thisInPropertyBoundDeclarations.types +++ b/tests/baselines/reference/thisInPropertyBoundDeclarations.types @@ -84,9 +84,9 @@ class A { >{ a: function() { return this; }, } : { a: () => any; } a: function() { return this; }, ->a : () => any ->function() { return this; } : () => any ->this : any +>a : () => { a: any; } +>function() { return this; } : () => { a: any; } +>this : { a: () => any; } }; @@ -98,9 +98,9 @@ class A { >{ a: function() { return this; }, } : { a: () => any; } a: function() { return this; }, ->a : () => any ->function() { return this; } : () => any ->this : any +>a : () => { a: any; } +>function() { return this; } : () => { a: any; } +>this : { a: () => any; } }; }; diff --git a/tests/baselines/reference/thisTypeInFunctions2.js b/tests/baselines/reference/thisTypeInFunctions2.js index f52438a19ab..45b26fe84d8 100644 --- a/tests/baselines/reference/thisTypeInFunctions2.js +++ b/tests/baselines/reference/thisTypeInFunctions2.js @@ -33,15 +33,14 @@ extend1({ }); extend2({ init() { - this // this: any because the contextual signature of init doesn't specify this' type + this // this: containing object literal type this.mine - this.willDestroy + //this.willDestroy }, mine: 13, foo() { - this // this: any because of the string indexer + this // this: containing object literal type this.mine - this.willDestroy } }); @@ -70,15 +69,14 @@ extend1({ }); extend2({ init: function () { - this; // this: any because the contextual signature of init doesn't specify this' type + this; // this: containing object literal type this.mine; - this.willDestroy; + //this.willDestroy }, mine: 13, foo: function () { - this; // this: any because of the string indexer + this; // this: containing object literal type this.mine; - this.willDestroy; } }); simple({ diff --git a/tests/baselines/reference/thisTypeInFunctions2.symbols b/tests/baselines/reference/thisTypeInFunctions2.symbols index 5cc26e3ad43..d9d0be723b6 100644 --- a/tests/baselines/reference/thisTypeInFunctions2.symbols +++ b/tests/baselines/reference/thisTypeInFunctions2.symbols @@ -89,9 +89,15 @@ extend2({ init() { >init : Symbol(init, Decl(thisTypeInFunctions2.ts, 32, 9)) - this // this: any because the contextual signature of init doesn't specify this' type + this // this: containing object literal type +>this : Symbol(__object, Decl(thisTypeInFunctions2.ts, 32, 8)) + this.mine - this.willDestroy +>this.mine : Symbol(mine, Decl(thisTypeInFunctions2.ts, 37, 6)) +>this : Symbol(__object, Decl(thisTypeInFunctions2.ts, 32, 8)) +>mine : Symbol(mine, Decl(thisTypeInFunctions2.ts, 37, 6)) + + //this.willDestroy }, mine: 13, >mine : Symbol(mine, Decl(thisTypeInFunctions2.ts, 37, 6)) @@ -99,9 +105,13 @@ extend2({ foo() { >foo : Symbol(foo, Decl(thisTypeInFunctions2.ts, 38, 13)) - this // this: any because of the string indexer + this // this: containing object literal type +>this : Symbol(__object, Decl(thisTypeInFunctions2.ts, 32, 8)) + this.mine - this.willDestroy +>this.mine : Symbol(mine, Decl(thisTypeInFunctions2.ts, 37, 6)) +>this : Symbol(__object, Decl(thisTypeInFunctions2.ts, 32, 8)) +>mine : Symbol(mine, Decl(thisTypeInFunctions2.ts, 37, 6)) } }); @@ -109,17 +119,20 @@ simple({ >simple : Symbol(simple, Decl(thisTypeInFunctions2.ts, 17, 57)) foo(n) { ->foo : Symbol(foo, Decl(thisTypeInFunctions2.ts, 46, 8)) ->n : Symbol(n, Decl(thisTypeInFunctions2.ts, 47, 8)) +>foo : Symbol(foo, Decl(thisTypeInFunctions2.ts, 45, 8)) +>n : Symbol(n, Decl(thisTypeInFunctions2.ts, 46, 8)) return n.length + this.bar(); >n.length : Symbol(String.length, Decl(lib.d.ts, --, --)) ->n : Symbol(n, Decl(thisTypeInFunctions2.ts, 47, 8)) +>n : Symbol(n, Decl(thisTypeInFunctions2.ts, 46, 8)) >length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>this.bar : Symbol(bar, Decl(thisTypeInFunctions2.ts, 48, 6)) +>this : Symbol(__object, Decl(thisTypeInFunctions2.ts, 45, 7)) +>bar : Symbol(bar, Decl(thisTypeInFunctions2.ts, 48, 6)) }, bar() { ->bar : Symbol(bar, Decl(thisTypeInFunctions2.ts, 49, 6)) +>bar : Symbol(bar, Decl(thisTypeInFunctions2.ts, 48, 6)) return 14; } diff --git a/tests/baselines/reference/thisTypeInFunctions2.types b/tests/baselines/reference/thisTypeInFunctions2.types index 3cf6c1d2fae..f79426529ea 100644 --- a/tests/baselines/reference/thisTypeInFunctions2.types +++ b/tests/baselines/reference/thisTypeInFunctions2.types @@ -92,26 +92,22 @@ extend1({ } }); extend2({ ->extend2({ init() { this // this: any because the contextual signature of init doesn't specify this' type this.mine this.willDestroy }, mine: 13, foo() { this // this: any because of the string indexer this.mine this.willDestroy }}) : void +>extend2({ init() { this // this: containing object literal type this.mine //this.willDestroy }, mine: 13, foo() { this // this: containing object literal type this.mine }}) : void >extend2 : (args: IndexedWithoutThis) => void ->{ init() { this // this: any because the contextual signature of init doesn't specify this' type this.mine this.willDestroy }, mine: 13, foo() { this // this: any because of the string indexer this.mine this.willDestroy }} : { init(): void; mine: number; foo(): void; } +>{ init() { this // this: containing object literal type this.mine //this.willDestroy }, mine: 13, foo() { this // this: containing object literal type this.mine }} : { init(): void; mine: number; foo(): void; } init() { >init : () => void - this // this: any because the contextual signature of init doesn't specify this' type ->this : any + this // this: containing object literal type +>this : { init(): void; mine: number; foo(): void; } this.mine ->this.mine : any ->this : any ->mine : any - - this.willDestroy ->this.willDestroy : any ->this : any ->willDestroy : any +>this.mine : number +>this : { init(): void; mine: number; foo(): void; } +>mine : number + //this.willDestroy }, mine: 13, >mine : number @@ -120,39 +116,34 @@ extend2({ foo() { >foo : () => void - this // this: any because of the string indexer ->this : any + this // this: containing object literal type +>this : { init(): void; mine: number; foo(): void; } this.mine ->this.mine : any ->this : any ->mine : any - - this.willDestroy ->this.willDestroy : any ->this : any ->willDestroy : any +>this.mine : number +>this : { init(): void; mine: number; foo(): void; } +>mine : number } }); simple({ >simple({ foo(n) { return n.length + this.bar(); }, bar() { return 14; }}) : void >simple : (arg: SimpleInterface) => void ->{ foo(n) { return n.length + this.bar(); }, bar() { return 14; }} : { foo(n: string): any; bar(): number; } +>{ foo(n) { return n.length + this.bar(); }, bar() { return 14; }} : { foo(n: string): number; bar(): number; } foo(n) { ->foo : (n: string) => any +>foo : (n: string) => number >n : string return n.length + this.bar(); ->n.length + this.bar() : any +>n.length + this.bar() : number >n.length : number >n : string >length : number ->this.bar() : any ->this.bar : any ->this : any ->bar : any +>this.bar() : number +>this.bar : () => number +>this : { foo(n: string): number; bar(): number; } +>bar : () => number }, bar() { diff --git a/tests/baselines/reference/thisTypeInObjectLiterals.symbols b/tests/baselines/reference/thisTypeInObjectLiterals.symbols index af4badf1c0f..ad786a4a247 100644 --- a/tests/baselines/reference/thisTypeInObjectLiterals.symbols +++ b/tests/baselines/reference/thisTypeInObjectLiterals.symbols @@ -9,11 +9,22 @@ let o = { >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(__object, Decl(thisTypeInObjectLiterals.ts, 0, 7)) +>d : Symbol(d, Decl(thisTypeInObjectLiterals.ts, 0, 9)) +>length : Symbol(String.length, Decl(lib.d.ts, --, --)) + }, f: function() { >f : Symbol(f, Decl(thisTypeInObjectLiterals.ts, 4, 6)) 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(__object, Decl(thisTypeInObjectLiterals.ts, 0, 7)) +>d : Symbol(d, Decl(thisTypeInObjectLiterals.ts, 0, 9)) +>length : Symbol(String.length, Decl(lib.d.ts, --, --)) } } @@ -27,12 +38,22 @@ let mutuallyRecursive = { >start : Symbol(start, Decl(thisTypeInObjectLiterals.ts, 11, 11)) return this.passthrough(this.a); +>this.passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 14, 6)) +>this : Symbol(__object, Decl(thisTypeInObjectLiterals.ts, 10, 23)) +>passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 14, 6)) +>this.a : Symbol(a, Decl(thisTypeInObjectLiterals.ts, 10, 25)) +>this : Symbol(__object, Decl(thisTypeInObjectLiterals.ts, 10, 23)) +>a : Symbol(a, Decl(thisTypeInObjectLiterals.ts, 10, 25)) + }, passthrough(n: number) { >passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 14, 6)) >n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 15, 16)) return this.sub1(n); +>this.sub1 : Symbol(sub1, Decl(thisTypeInObjectLiterals.ts, 17, 6)) +>this : Symbol(__object, Decl(thisTypeInObjectLiterals.ts, 10, 23)) +>sub1 : Symbol(sub1, Decl(thisTypeInObjectLiterals.ts, 17, 6)) >n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 15, 16)) }, @@ -44,6 +65,9 @@ let mutuallyRecursive = { >n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 18, 9)) return this.passthrough(n - 1); +>this.passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 14, 6)) +>this : Symbol(__object, Decl(thisTypeInObjectLiterals.ts, 10, 23)) +>passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 14, 6)) >n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 18, 9)) } return n; diff --git a/tests/baselines/reference/thisTypeInObjectLiterals.types b/tests/baselines/reference/thisTypeInObjectLiterals.types index 240cfaa54f9..d5c6d851faf 100644 --- a/tests/baselines/reference/thisTypeInObjectLiterals.types +++ b/tests/baselines/reference/thisTypeInObjectLiterals.types @@ -1,66 +1,66 @@ === tests/cases/conformance/types/thisType/thisTypeInObjectLiterals.ts === let o = { ->o : { d: string; m(): any; f: () => any; } ->{ d: "bar", m() { return this.d.length; }, f: function() { return this.d.length; }} : { d: string; m(): any; f: () => any; } +>o : { d: string; m(): number; f: () => number; } +>{ d: "bar", m() { return this.d.length; }, f: function() { return this.d.length; }} : { d: string; m(): number; f: () => number; } d: "bar", >d : string >"bar" : "bar" m() { ->m : () => any +>m : () => number return this.d.length; ->this.d.length : any ->this.d : any ->this : any ->d : any ->length : any +>this.d.length : number +>this.d : string +>this : { d: string; m(): number; f: () => number; } +>d : string +>length : number }, f: function() { ->f : () => any ->function() { return this.d.length; } : () => any +>f : () => number +>function() { return this.d.length; } : () => number return this.d.length; ->this.d.length : any ->this.d : any ->this : any ->d : any ->length : any +>this.d.length : number +>this.d : string +>this : { d: string; m(): number; f: () => number; } +>d : string +>length : number } } let mutuallyRecursive = { ->mutuallyRecursive : { a: number; start(): any; passthrough(n: number): any; sub1(n: number): number; } ->{ a: 100, start() { return this.passthrough(this.a); }, passthrough(n: number) { return this.sub1(n); }, sub1(n: number): number { if (n > 0) { return this.passthrough(n - 1); } return n; }} : { a: number; start(): any; passthrough(n: number): any; sub1(n: number): number; } +>mutuallyRecursive : { a: number; start(): number; passthrough(n: number): number; sub1(n: number): number; } +>{ a: 100, start() { return this.passthrough(this.a); }, passthrough(n: number) { return this.sub1(n); }, sub1(n: number): number { if (n > 0) { return this.passthrough(n - 1); } return n; }} : { a: number; start(): number; passthrough(n: number): number; sub1(n: number): number; } a: 100, >a : number >100 : 100 start() { ->start : () => any +>start : () => number return this.passthrough(this.a); ->this.passthrough(this.a) : any ->this.passthrough : any ->this : any ->passthrough : any ->this.a : any ->this : any ->a : any +>this.passthrough(this.a) : number +>this.passthrough : (n: number) => number +>this : { a: number; start(): number; passthrough(n: number): number; sub1(n: number): number; } +>passthrough : (n: number) => number +>this.a : number +>this : { a: number; start(): number; passthrough(n: number): number; sub1(n: number): number; } +>a : number }, passthrough(n: number) { ->passthrough : (n: number) => any +>passthrough : (n: number) => number >n : number return this.sub1(n); ->this.sub1(n) : any ->this.sub1 : any ->this : any ->sub1 : any +>this.sub1(n) : number +>this.sub1 : (n: number) => number +>this : { a: number; start(): number; passthrough(n: number): number; sub1(n: number): number; } +>sub1 : (n: number) => number >n : number }, @@ -74,10 +74,10 @@ let mutuallyRecursive = { >0 : 0 return this.passthrough(n - 1); ->this.passthrough(n - 1) : any ->this.passthrough : any ->this : any ->passthrough : any +>this.passthrough(n - 1) : number +>this.passthrough : (n: number) => number +>this : { a: number; start(): number; passthrough(n: number): number; sub1(n: number): number; } +>passthrough : (n: number) => number >n - 1 : number >n : number >1 : 1 @@ -88,10 +88,10 @@ let mutuallyRecursive = { } var i: number = mutuallyRecursive.start(); >i : number ->mutuallyRecursive.start() : any ->mutuallyRecursive.start : () => any ->mutuallyRecursive : { a: number; start(): any; passthrough(n: number): any; sub1(n: number): number; } ->start : () => any +>mutuallyRecursive.start() : number +>mutuallyRecursive.start : () => number +>mutuallyRecursive : { a: number; start(): number; passthrough(n: number): number; sub1(n: number): number; } +>start : () => number interface I { >I : I @@ -113,5 +113,5 @@ interface I { var impl: I = mutuallyRecursive; >impl : I >I : I ->mutuallyRecursive : { a: number; start(): any; passthrough(n: number): any; sub1(n: number): number; } +>mutuallyRecursive : { a: number; start(): number; passthrough(n: number): number; sub1(n: number): number; } diff --git a/tests/baselines/reference/throwInEnclosingStatements.symbols b/tests/baselines/reference/throwInEnclosingStatements.symbols index 63ed9dde578..94f7baee021 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(__object, Decl(throwInEnclosingStatements.ts, 40, 8)) } } diff --git a/tests/baselines/reference/throwInEnclosingStatements.types b/tests/baselines/reference/throwInEnclosingStatements.types index 2d99ac435ae..d859bbd6392 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/baselines/reference/underscoreTest1.symbols b/tests/baselines/reference/underscoreTest1.symbols index 89815bd2371..018633344eb 100644 --- a/tests/baselines/reference/underscoreTest1.symbols +++ b/tests/baselines/reference/underscoreTest1.symbols @@ -395,10 +395,16 @@ var buttonView = { onClick: function () { alert('clicked: ' + this.label); }, >onClick : Symbol(onClick, Decl(underscoreTest1_underscoreTests.ts, 97, 24)) >alert : Symbol(alert, Decl(underscoreTest1_underscoreTests.ts, 2, 14)) +>this.label : Symbol(label, Decl(underscoreTest1_underscoreTests.ts, 96, 18)) +>this : Symbol(__object, Decl(underscoreTest1_underscoreTests.ts, 96, 16)) +>label : Symbol(label, Decl(underscoreTest1_underscoreTests.ts, 96, 18)) onHover: function () { alert('hovering: ' + this.label); } >onHover : Symbol(onHover, Decl(underscoreTest1_underscoreTests.ts, 98, 62)) >alert : Symbol(alert, Decl(underscoreTest1_underscoreTests.ts, 2, 14)) +>this.label : Symbol(label, Decl(underscoreTest1_underscoreTests.ts, 96, 18)) +>this : Symbol(__object, Decl(underscoreTest1_underscoreTests.ts, 96, 16)) +>label : Symbol(label, Decl(underscoreTest1_underscoreTests.ts, 96, 18)) }; _.bindAll(buttonView); diff --git a/tests/baselines/reference/underscoreTest1.types b/tests/baselines/reference/underscoreTest1.types index 97e064fb12c..0af9b55d25a 100644 --- a/tests/baselines/reference/underscoreTest1.types +++ b/tests/baselines/reference/underscoreTest1.types @@ -827,9 +827,9 @@ var buttonView = { >alert : (x: string) => void >'clicked: ' + this.label : string >'clicked: ' : "clicked: " ->this.label : any ->this : any ->label : any +>this.label : string +>this : { label: string; onClick: () => void; onHover: () => void; } +>label : string onHover: function () { alert('hovering: ' + this.label); } >onHover : () => void @@ -838,9 +838,9 @@ var buttonView = { >alert : (x: string) => void >'hovering: ' + this.label : string >'hovering: ' : "hovering: " ->this.label : any ->this : any ->label : any +>this.label : string +>this : { label: string; onClick: () => void; onHover: () => void; } +>label : string }; _.bindAll(buttonView); From 27346b13d039a694ff815db81ba6f6df5667fe2e Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 16 Feb 2017 20:22:46 -0800 Subject: [PATCH 06/65] Accept new baselines --- tests/baselines/reference/fatarrowfunctions.symbols | 2 +- .../reference/fatarrowfunctionsInFunctions.symbols | 2 +- tests/baselines/reference/objectSpread.symbols | 2 +- tests/baselines/reference/selfInLambdas.symbols | 4 ++-- tests/baselines/reference/thisBinding2.symbols | 2 +- .../reference/thisTypeInObjectLiterals.symbols | 12 ++++++------ .../reference/throwInEnclosingStatements.symbols | 2 +- tests/baselines/reference/underscoreTest1.symbols | 4 ++-- 8 files changed, 15 insertions(+), 15 deletions(-) diff --git a/tests/baselines/reference/fatarrowfunctions.symbols b/tests/baselines/reference/fatarrowfunctions.symbols index 1e5fb4f3178..25213a9bbf8 100644 --- a/tests/baselines/reference/fatarrowfunctions.symbols +++ b/tests/baselines/reference/fatarrowfunctions.symbols @@ -165,7 +165,7 @@ var messenger = { >setTimeout : Symbol(setTimeout, Decl(fatarrowfunctions.ts, 34, 1)) >this.message.toString : Symbol(String.toString, Decl(lib.d.ts, --, --)) >this.message : Symbol(message, Decl(fatarrowfunctions.ts, 38, 17)) ->this : Symbol(__object, Decl(fatarrowfunctions.ts, 38, 15)) +>this : Symbol(messenger, Decl(fatarrowfunctions.ts, 38, 15)) >message : Symbol(message, Decl(fatarrowfunctions.ts, 38, 17)) >toString : Symbol(String.toString, Decl(lib.d.ts, --, --)) } diff --git a/tests/baselines/reference/fatarrowfunctionsInFunctions.symbols b/tests/baselines/reference/fatarrowfunctionsInFunctions.symbols index f1123f4aa96..977dd39460d 100644 --- a/tests/baselines/reference/fatarrowfunctionsInFunctions.symbols +++ b/tests/baselines/reference/fatarrowfunctionsInFunctions.symbols @@ -16,7 +16,7 @@ var messenger = { var _self = this; >_self : Symbol(_self, Decl(fatarrowfunctionsInFunctions.ts, 5, 11)) ->this : Symbol(__object, Decl(fatarrowfunctionsInFunctions.ts, 2, 15)) +>this : Symbol(messenger, Decl(fatarrowfunctionsInFunctions.ts, 2, 15)) setTimeout(function() { >setTimeout : Symbol(setTimeout, Decl(fatarrowfunctionsInFunctions.ts, 0, 0)) diff --git a/tests/baselines/reference/objectSpread.symbols b/tests/baselines/reference/objectSpread.symbols index 3487f757aeb..a734066d5e7 100644 --- a/tests/baselines/reference/objectSpread.symbols +++ b/tests/baselines/reference/objectSpread.symbols @@ -201,7 +201,7 @@ let cplus: { p: number, plus(): void } = { ...c, plus() { return this.p + 1; } } >c : Symbol(c, Decl(objectSpread.ts, 45, 3)) >plus : Symbol(plus, Decl(objectSpread.ts, 49, 48)) >this.p : Symbol(C.p, Decl(objectSpread.ts, 44, 9)) ->this : Symbol(__object, Decl(objectSpread.ts, 49, 40)) +>this : Symbol(cplus, Decl(objectSpread.ts, 49, 40)) >p : Symbol(C.p, Decl(objectSpread.ts, 44, 9)) cplus.plus(); diff --git a/tests/baselines/reference/selfInLambdas.symbols b/tests/baselines/reference/selfInLambdas.symbols index 6f91adefcc1..0a51113710b 100644 --- a/tests/baselines/reference/selfInLambdas.symbols +++ b/tests/baselines/reference/selfInLambdas.symbols @@ -38,13 +38,13 @@ var o = { this.counter++ >this.counter : Symbol(counter, Decl(selfInLambdas.ts, 10, 9)) ->this : Symbol(__object, Decl(selfInLambdas.ts, 10, 7)) +>this : Symbol(o, Decl(selfInLambdas.ts, 10, 7)) >counter : Symbol(counter, Decl(selfInLambdas.ts, 10, 9)) var f = () => this.counter; >f : Symbol(f, Decl(selfInLambdas.ts, 18, 15)) >this.counter : Symbol(counter, Decl(selfInLambdas.ts, 10, 9)) ->this : Symbol(__object, Decl(selfInLambdas.ts, 10, 7)) +>this : Symbol(o, Decl(selfInLambdas.ts, 10, 7)) >counter : Symbol(counter, Decl(selfInLambdas.ts, 10, 9)) } diff --git a/tests/baselines/reference/thisBinding2.symbols b/tests/baselines/reference/thisBinding2.symbols index 507b7e48419..f8436f5248b 100644 --- a/tests/baselines/reference/thisBinding2.symbols +++ b/tests/baselines/reference/thisBinding2.symbols @@ -51,7 +51,7 @@ var messenger = { >setTimeout : Symbol(setTimeout, Decl(thisBinding2.ts, 12, 1)) >x : Symbol(x, Decl(thisBinding2.ts, 17, 37)) >this.message : Symbol(message, Decl(thisBinding2.ts, 14, 17)) ->this : Symbol(__object, Decl(thisBinding2.ts, 14, 15)) +>this : Symbol(messenger, Decl(thisBinding2.ts, 14, 15)) >message : Symbol(message, Decl(thisBinding2.ts, 14, 17)) } }; diff --git a/tests/baselines/reference/thisTypeInObjectLiterals.symbols b/tests/baselines/reference/thisTypeInObjectLiterals.symbols index ad786a4a247..fd6d6ecebd5 100644 --- a/tests/baselines/reference/thisTypeInObjectLiterals.symbols +++ b/tests/baselines/reference/thisTypeInObjectLiterals.symbols @@ -11,7 +11,7 @@ let o = { 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(__object, Decl(thisTypeInObjectLiterals.ts, 0, 7)) +>this : Symbol(o, Decl(thisTypeInObjectLiterals.ts, 0, 7)) >d : Symbol(d, Decl(thisTypeInObjectLiterals.ts, 0, 9)) >length : Symbol(String.length, Decl(lib.d.ts, --, --)) @@ -22,7 +22,7 @@ let o = { 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(__object, Decl(thisTypeInObjectLiterals.ts, 0, 7)) +>this : Symbol(o, Decl(thisTypeInObjectLiterals.ts, 0, 7)) >d : Symbol(d, Decl(thisTypeInObjectLiterals.ts, 0, 9)) >length : Symbol(String.length, Decl(lib.d.ts, --, --)) } @@ -39,10 +39,10 @@ let mutuallyRecursive = { return this.passthrough(this.a); >this.passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 14, 6)) ->this : Symbol(__object, Decl(thisTypeInObjectLiterals.ts, 10, 23)) +>this : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 10, 23)) >passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 14, 6)) >this.a : Symbol(a, Decl(thisTypeInObjectLiterals.ts, 10, 25)) ->this : Symbol(__object, Decl(thisTypeInObjectLiterals.ts, 10, 23)) +>this : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 10, 23)) >a : Symbol(a, Decl(thisTypeInObjectLiterals.ts, 10, 25)) }, @@ -52,7 +52,7 @@ let mutuallyRecursive = { return this.sub1(n); >this.sub1 : Symbol(sub1, Decl(thisTypeInObjectLiterals.ts, 17, 6)) ->this : Symbol(__object, Decl(thisTypeInObjectLiterals.ts, 10, 23)) +>this : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 10, 23)) >sub1 : Symbol(sub1, Decl(thisTypeInObjectLiterals.ts, 17, 6)) >n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 15, 16)) @@ -66,7 +66,7 @@ let mutuallyRecursive = { return this.passthrough(n - 1); >this.passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 14, 6)) ->this : Symbol(__object, Decl(thisTypeInObjectLiterals.ts, 10, 23)) +>this : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 10, 23)) >passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 14, 6)) >n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 18, 9)) } diff --git a/tests/baselines/reference/throwInEnclosingStatements.symbols b/tests/baselines/reference/throwInEnclosingStatements.symbols index 94f7baee021..36dcd3cfcbd 100644 --- a/tests/baselines/reference/throwInEnclosingStatements.symbols +++ b/tests/baselines/reference/throwInEnclosingStatements.symbols @@ -89,7 +89,7 @@ var aa = { >biz : Symbol(biz, Decl(throwInEnclosingStatements.ts, 41, 10)) throw this; ->this : Symbol(__object, Decl(throwInEnclosingStatements.ts, 40, 8)) +>this : Symbol(aa, Decl(throwInEnclosingStatements.ts, 40, 8)) } } diff --git a/tests/baselines/reference/underscoreTest1.symbols b/tests/baselines/reference/underscoreTest1.symbols index 459674cdbe8..3b578be8165 100644 --- a/tests/baselines/reference/underscoreTest1.symbols +++ b/tests/baselines/reference/underscoreTest1.symbols @@ -396,14 +396,14 @@ var buttonView = { >onClick : Symbol(onClick, Decl(underscoreTest1_underscoreTests.ts, 97, 24)) >alert : Symbol(alert, Decl(underscoreTest1_underscoreTests.ts, 2, 14)) >this.label : Symbol(label, Decl(underscoreTest1_underscoreTests.ts, 96, 18)) ->this : Symbol(__object, Decl(underscoreTest1_underscoreTests.ts, 96, 16)) +>this : Symbol(buttonView, Decl(underscoreTest1_underscoreTests.ts, 96, 16)) >label : Symbol(label, Decl(underscoreTest1_underscoreTests.ts, 96, 18)) onHover: function () { alert('hovering: ' + this.label); } >onHover : Symbol(onHover, Decl(underscoreTest1_underscoreTests.ts, 98, 62)) >alert : Symbol(alert, Decl(underscoreTest1_underscoreTests.ts, 2, 14)) >this.label : Symbol(label, Decl(underscoreTest1_underscoreTests.ts, 96, 18)) ->this : Symbol(__object, Decl(underscoreTest1_underscoreTests.ts, 96, 16)) +>this : Symbol(buttonView, Decl(underscoreTest1_underscoreTests.ts, 96, 16)) >label : Symbol(label, Decl(underscoreTest1_underscoreTests.ts, 96, 18)) }; From 0eec41ee63decfadfdc81f4323dc987a31b0b718 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Thu, 16 Feb 2017 22:53:41 -0800 Subject: [PATCH 07/65] Simplify helpers --- src/compiler/transformers/destructuring.ts | 2 +- src/compiler/utilities.ts | 17 ++++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/compiler/transformers/destructuring.ts b/src/compiler/transformers/destructuring.ts index b4473e6a261..48403cc89db 100644 --- a/src/compiler/transformers/destructuring.ts +++ b/src/compiler/transformers/destructuring.ts @@ -42,7 +42,7 @@ namespace ts { let value: Expression; if (isDestructuringAssignment(node)) { value = node.right; - while (isEmptyObjectLiteralOrArrayLiteral(node.left)) { + while (isEmptyArrayLiteral(node.left) || isEmptyObjectLiteral(node.left)) { if (isDestructuringAssignment(value)) { location = node = value; value = node.right; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 97137090d38..34c7a0bdb02 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -3093,15 +3093,14 @@ namespace ts { (node.parent.kind === SyntaxKind.PropertyAccessExpression && (node.parent).name === node); } - export function isEmptyObjectLiteralOrArrayLiteral(expression: Node): boolean { - const kind = expression.kind; - if (kind === SyntaxKind.ObjectLiteralExpression) { - return (expression).properties.length === 0; - } - if (kind === SyntaxKind.ArrayLiteralExpression) { - return (expression).elements.length === 0; - } - return false; + export function isEmptyObjectLiteral(expression: Node): boolean { + return expression.kind === SyntaxKind.ObjectLiteralExpression && + (expression).properties.length === 0; + } + + export function isEmptyArrayLiteral(expression: Node): boolean { + return expression.kind === SyntaxKind.ArrayLiteralExpression && + (expression).elements.length === 0; } export function getLocalSymbolForExportDefault(symbol: Symbol) { From e3a0687327128c4cce55b8ce448ce8ad7d3fca9b Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 17 Feb 2017 06:56:58 -0800 Subject: [PATCH 08/65] Contextual this in 'obj.xxx = function(...)' or 'obj[xxx] = function(...)' --- src/compiler/checker.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3208d303ab0..9fb71884c51 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11518,6 +11518,14 @@ namespace ts { // for 'this' is the type of the object literal itself. return checkExpressionCached(containingLiteral); } + // In an assignment of the form 'obj.xxx = function(...)' or 'obj[xxx] = function(...)', the + // contextual type for 'this' is 'obj'. + if (func.parent.kind === SyntaxKind.BinaryExpression && (func.parent).operatorToken.kind === SyntaxKind.EqualsToken) { + const target = (func.parent).left; + if (target.kind === SyntaxKind.PropertyAccessExpression || target.kind === SyntaxKind.ElementAccessExpression) { + return checkExpressionCached((target).expression); + } + } } return undefined; } From 1d339de34230493b8b521d3335d2ca8e0e170b00 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Sat, 18 Feb 2017 14:17:12 -0800 Subject: [PATCH 09/65] Fix #14171: Recognize property assignements to `module.export` aliases as exports --- src/compiler/binder.ts | 46 +- src/compiler/utilities.ts | 15 + .../reference/moduleExportAlias.symbols | 227 ++++++++++ .../reference/moduleExportAlias.types | 395 ++++++++++++++++++ .../conformance/salsa/moduleExportAlias.ts | 79 ++++ 5 files changed, 761 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/moduleExportAlias.symbols create mode 100644 tests/baselines/reference/moduleExportAlias.types create mode 100644 tests/cases/conformance/salsa/moduleExportAlias.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 4837b673132..5aafa13da9e 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2227,7 +2227,42 @@ namespace ts { declareSymbol(file.symbol.exports, file.symbol, node.left, SymbolFlags.Property | SymbolFlags.Export, SymbolFlags.None); } + function isExportsOrModuleExportsOrAlias(node: Node): boolean { + return isExportsIdentifier(node) || + isModuleExportsPropertyAccessExpression(node) || + isNameOfExportsOrModuleExportsAliasDeclaration(node); + } + + function isNameOfExportsOrModuleExportsAliasDeclaration(node: Node) { + if (node.kind === SyntaxKind.Identifier) { + const symbol = container.locals.get((node).text); + if (symbol && symbol.valueDeclaration && symbol.valueDeclaration.kind === SyntaxKind.VariableDeclaration) { + const declaration = symbol.valueDeclaration as VariableDeclaration; + if (declaration.initializer) { + return isExportsOrModuleExportsOrAliasOrAssignemnt(declaration.initializer); + } + } + } + return false; + } + + function isExportsOrModuleExportsOrAliasOrAssignemnt(node: Node): boolean { + return isExportsOrModuleExportsOrAlias(node) || + (isAssignmentExpression(node, /*excludeCompoundAssignements*/ true) && (isExportsOrModuleExportsOrAliasOrAssignemnt(node.left) || isExportsOrModuleExportsOrAliasOrAssignemnt(node.right))); + } + function bindModuleExportsAssignment(node: BinaryExpression) { + // A common practice in node modules is to set 'export = module.exports = {}', this ensures that 'exports' + // is still pointing to 'module.exports'. + // We do not want to consider this as 'export=' since a module can have only one of these. + // Similarlly we do not want to treat 'module.exports = exports' as an 'export='. + const assignedExpression = getRightMostAssignedExpression(node.right); + if (isEmptyObjectLiteral(assignedExpression) || isExportsOrModuleExportsOrAlias(assignedExpression)) { + // Mark it as a module in case there are no other exports in the file + setCommonJsModuleIndicator(node); + return; + } + // 'module.exports = expr' assignment setCommonJsModuleIndicator(node); declareSymbol(file.symbol.exports, file.symbol, node, SymbolFlags.Property | SymbolFlags.Export | SymbolFlags.ValueModule, SymbolFlags.None); @@ -2284,11 +2319,20 @@ namespace ts { leftSideOfAssignment.parent = node; target.parent = leftSideOfAssignment; - bindPropertyAssignment(target.text, leftSideOfAssignment, /*isPrototypeProperty*/ false); + if (isNameOfExportsOrModuleExportsAliasDeclaration(target)) { + // This can be an alias for the 'exports' or 'module.exports' names, e.g. + // var util = module.exports; + // util.property = function ... + bindExportsPropertyAssignment(node); + } + else { + bindPropertyAssignment(target.text, leftSideOfAssignment, /*isPrototypeProperty*/ false); + } } function bindPropertyAssignment(functionName: string, propertyAccessExpression: PropertyAccessExpression, isPrototypeProperty: boolean) { let targetSymbol = container.locals.get(functionName); + if (targetSymbol && isDeclarationOfFunctionOrClassExpression(targetSymbol)) { targetSymbol = (targetSymbol.valueDeclaration as VariableDeclaration).initializer.symbol; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 34c7a0bdb02..51613c14b6f 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1425,6 +1425,21 @@ namespace ts { return false; } + export function getRightMostAssignedExpression(node: Node) { + while (isAssignmentExpression(node, /*excludeCompoundAssignements*/ true)) { + node = node.right; + } + return node; + } + + export function isExportsIdentifier(node: Node) { + return isIdentifier(node) && node.text === "exports"; + } + + export function isModuleExportsPropertyAccessExpression(node: Node) { + return isPropertyAccessExpression(node) && isIdentifier(node.expression) && node.expression.text === "module" && node.name.text === "exports"; + } + /// Given a BinaryExpression, returns SpecialPropertyAssignmentKind for the various kinds of property /// assignments we treat as special in the binder export function getSpecialPropertyAssignmentKind(expression: Node): SpecialPropertyAssignmentKind { diff --git a/tests/baselines/reference/moduleExportAlias.symbols b/tests/baselines/reference/moduleExportAlias.symbols new file mode 100644 index 00000000000..b78b6e214f3 --- /dev/null +++ b/tests/baselines/reference/moduleExportAlias.symbols @@ -0,0 +1,227 @@ +=== tests/cases/conformance/salsa/a.ts === + +import b = require("./b.js"); +>b : Symbol(b, Decl(a.ts, 0, 0)) + +b.func1; +>b.func1 : Symbol(b.func1, Decl(b.js, 0, 27)) +>b : Symbol(b, Decl(a.ts, 0, 0)) +>func1 : Symbol(b.func1, Decl(b.js, 0, 27)) + +b.func2; +>b.func2 : Symbol(b.func2, Decl(b.js, 1, 37)) +>b : Symbol(b, Decl(a.ts, 0, 0)) +>func2 : Symbol(b.func2, Decl(b.js, 1, 37)) + +b.func3; +>b.func3 : Symbol(b.func3, Decl(b.js, 4, 40)) +>b : Symbol(b, Decl(a.ts, 0, 0)) +>func3 : Symbol(b.func3, Decl(b.js, 4, 40)) + +b.func4; +>b.func4 : Symbol(b.func4, Decl(b.js, 5, 43)) +>b : Symbol(b, Decl(a.ts, 0, 0)) +>func4 : Symbol(b.func4, Decl(b.js, 5, 43)) + +b.func5; +>b.func5 : Symbol(b.func5, Decl(b.js, 8, 57)) +>b : Symbol(b, Decl(a.ts, 0, 0)) +>func5 : Symbol(b.func5, Decl(b.js, 8, 57)) + +b.func6; +>b.func6 : Symbol(b.func6, Decl(b.js, 11, 57)) +>b : Symbol(b, Decl(a.ts, 0, 0)) +>func6 : Symbol(b.func6, Decl(b.js, 11, 57)) + +b.func7; +>b.func7 : Symbol(b.func7, Decl(b.js, 15, 60)) +>b : Symbol(b, Decl(a.ts, 0, 0)) +>func7 : Symbol(b.func7, Decl(b.js, 15, 60)) + +b.func8; +>b.func8 : Symbol(b.func8, Decl(b.js, 18, 67)) +>b : Symbol(b, Decl(a.ts, 0, 0)) +>func8 : Symbol(b.func8, Decl(b.js, 18, 67)) + +b.func9; +>b.func9 : Symbol(b.func9, Decl(b.js, 21, 62)) +>b : Symbol(b, Decl(a.ts, 0, 0)) +>func9 : Symbol(b.func9, Decl(b.js, 21, 62)) + +b.func10; +>b.func10 : Symbol(b.func10, Decl(b.js, 24, 62)) +>b : Symbol(b, Decl(a.ts, 0, 0)) +>func10 : Symbol(b.func10, Decl(b.js, 24, 62)) + +b.func11; +>b.func11 : Symbol(b.func11, Decl(b.js, 27, 50), Decl(b.js, 31, 50)) +>b : Symbol(b, Decl(a.ts, 0, 0)) +>func11 : Symbol(b.func11, Decl(b.js, 27, 50), Decl(b.js, 31, 50)) + +b.func12; +>b.func12 : Symbol(b.func12, Decl(b.js, 28, 33), Decl(b.js, 32, 33)) +>b : Symbol(b, Decl(a.ts, 0, 0)) +>func12 : Symbol(b.func12, Decl(b.js, 28, 33), Decl(b.js, 32, 33)) + +b.func13; +>b.func13 : Symbol(b.func13, Decl(b.js, 35, 30)) +>b : Symbol(b, Decl(a.ts, 0, 0)) +>func13 : Symbol(b.func13, Decl(b.js, 35, 30)) + +b.func14; +>b.func14 : Symbol(b.func14, Decl(b.js, 36, 33)) +>b : Symbol(b, Decl(a.ts, 0, 0)) +>func14 : Symbol(b.func14, Decl(b.js, 36, 33)) + +b.func15; +>b.func15 : Symbol(b.func15, Decl(b.js, 39, 30)) +>b : Symbol(b, Decl(a.ts, 0, 0)) +>func15 : Symbol(b.func15, Decl(b.js, 39, 30)) + +b.func16; +>b.func16 : Symbol(b.func16, Decl(b.js, 40, 33)) +>b : Symbol(b, Decl(a.ts, 0, 0)) +>func16 : Symbol(b.func16, Decl(b.js, 40, 33)) + +b.func17; +>b.func17 : Symbol(b.func17, Decl(b.js, 43, 30)) +>b : Symbol(b, Decl(a.ts, 0, 0)) +>func17 : Symbol(b.func17, Decl(b.js, 43, 30)) + +b.func18; +>b.func18 : Symbol(b.func18, Decl(b.js, 44, 33)) +>b : Symbol(b, Decl(a.ts, 0, 0)) +>func18 : Symbol(b.func18, Decl(b.js, 44, 33)) + +b.func19; +>b.func19 : Symbol(b.func19, Decl(b.js, 47, 20)) +>b : Symbol(b, Decl(a.ts, 0, 0)) +>func19 : Symbol(b.func19, Decl(b.js, 47, 20)) + +b.func20; +>b.func20 : Symbol(b.func20, Decl(b.js, 48, 33)) +>b : Symbol(b, Decl(a.ts, 0, 0)) +>func20 : Symbol(b.func20, Decl(b.js, 48, 33)) + + +=== tests/cases/conformance/salsa/b.js === +var exportsAlias = exports; +>exportsAlias : Symbol(exportsAlias, Decl(b.js, 0, 3)) + +exportsAlias.func1 = function () { }; +>exportsAlias : Symbol(exportsAlias, Decl(b.js, 0, 3)) + +exports.func2 = function () { }; +>exports : Symbol(func2, Decl(b.js, 1, 37)) +>func2 : Symbol(func2, Decl(b.js, 1, 37)) + +var moduleExportsAlias = module.exports; +>moduleExportsAlias : Symbol(moduleExportsAlias, Decl(b.js, 4, 3)) + +moduleExportsAlias.func3 = function () { }; +>moduleExportsAlias : Symbol(moduleExportsAlias, Decl(b.js, 4, 3)) + +module.exports.func4 = function () { }; +>module.exports : Symbol(func4, Decl(b.js, 5, 43)) +>func4 : Symbol(func4, Decl(b.js, 5, 43)) + +var multipleDeclarationAlias1 = exports = module.exports; +>multipleDeclarationAlias1 : Symbol(multipleDeclarationAlias1, Decl(b.js, 8, 3)) + +multipleDeclarationAlias1.func5 = function () { }; +>multipleDeclarationAlias1 : Symbol(multipleDeclarationAlias1, Decl(b.js, 8, 3)) + +var multipleDeclarationAlias2 = module.exports = exports; +>multipleDeclarationAlias2 : Symbol(multipleDeclarationAlias2, Decl(b.js, 11, 3)) + +multipleDeclarationAlias2.func6 = function () { }; +>multipleDeclarationAlias2 : Symbol(multipleDeclarationAlias2, Decl(b.js, 11, 3)) + +var someOtherVariable; +>someOtherVariable : Symbol(someOtherVariable, Decl(b.js, 14, 3)) + +var multipleDeclarationAlias3 = someOtherVariable = exports; +>multipleDeclarationAlias3 : Symbol(multipleDeclarationAlias3, Decl(b.js, 15, 3)) +>someOtherVariable : Symbol(someOtherVariable, Decl(b.js, 14, 3)) + +multipleDeclarationAlias3.func7 = function () { }; +>multipleDeclarationAlias3 : Symbol(multipleDeclarationAlias3, Decl(b.js, 15, 3)) + +var multipleDeclarationAlias4 = someOtherVariable = module.exports; +>multipleDeclarationAlias4 : Symbol(multipleDeclarationAlias4, Decl(b.js, 18, 3)) +>someOtherVariable : Symbol(someOtherVariable, Decl(b.js, 14, 3)) + +multipleDeclarationAlias4.func8 = function () { }; +>multipleDeclarationAlias4 : Symbol(multipleDeclarationAlias4, Decl(b.js, 18, 3)) + +var multipleDeclarationAlias5 = module.exports = exports = {}; +>multipleDeclarationAlias5 : Symbol(multipleDeclarationAlias5, Decl(b.js, 21, 3)) + +multipleDeclarationAlias5.func9 = function () { }; +>multipleDeclarationAlias5 : Symbol(multipleDeclarationAlias5, Decl(b.js, 21, 3)) + +var multipleDeclarationAlias6 = exports = module.exports = {}; +>multipleDeclarationAlias6 : Symbol(multipleDeclarationAlias6, Decl(b.js, 24, 3)) + +multipleDeclarationAlias6.func10 = function () { }; +>multipleDeclarationAlias6 : Symbol(multipleDeclarationAlias6, Decl(b.js, 24, 3)) + +exports = module.exports = someOtherVariable = {}; +>someOtherVariable : Symbol(someOtherVariable, Decl(b.js, 14, 3)) + +exports.func11 = function () { }; +>exports : Symbol(func11, Decl(b.js, 27, 50), Decl(b.js, 31, 50)) +>func11 : Symbol(func11, Decl(b.js, 27, 50), Decl(b.js, 31, 50)) + +module.exports.func12 = function () { }; +>module.exports : Symbol(func12, Decl(b.js, 28, 33), Decl(b.js, 32, 33)) +>func12 : Symbol(func12, Decl(b.js, 28, 33), Decl(b.js, 32, 33)) + +exports = module.exports = someOtherVariable = {}; +>someOtherVariable : Symbol(someOtherVariable, Decl(b.js, 14, 3)) + +exports.func11 = function () { }; +>exports : Symbol(func11, Decl(b.js, 27, 50), Decl(b.js, 31, 50)) +>func11 : Symbol(func11, Decl(b.js, 27, 50), Decl(b.js, 31, 50)) + +module.exports.func12 = function () { }; +>module.exports : Symbol(func12, Decl(b.js, 28, 33), Decl(b.js, 32, 33)) +>func12 : Symbol(func12, Decl(b.js, 28, 33), Decl(b.js, 32, 33)) + +exports = module.exports = {}; +exports.func13 = function () { }; +>exports : Symbol(func13, Decl(b.js, 35, 30)) +>func13 : Symbol(func13, Decl(b.js, 35, 30)) + +module.exports.func14 = function () { }; +>module.exports : Symbol(func14, Decl(b.js, 36, 33)) +>func14 : Symbol(func14, Decl(b.js, 36, 33)) + +exports = module.exports = {}; +exports.func15 = function () { }; +>exports : Symbol(func15, Decl(b.js, 39, 30)) +>func15 : Symbol(func15, Decl(b.js, 39, 30)) + +module.exports.func16 = function () { }; +>module.exports : Symbol(func16, Decl(b.js, 40, 33)) +>func16 : Symbol(func16, Decl(b.js, 40, 33)) + +module.exports = exports = {}; +exports.func17 = function () { }; +>exports : Symbol(func17, Decl(b.js, 43, 30)) +>func17 : Symbol(func17, Decl(b.js, 43, 30)) + +module.exports.func18 = function () { }; +>module.exports : Symbol(func18, Decl(b.js, 44, 33)) +>func18 : Symbol(func18, Decl(b.js, 44, 33)) + +module.exports = {}; +exports.func19 = function () { }; +>exports : Symbol(func19, Decl(b.js, 47, 20)) +>func19 : Symbol(func19, Decl(b.js, 47, 20)) + +module.exports.func20 = function () { }; +>module.exports : Symbol(func20, Decl(b.js, 48, 33)) +>func20 : Symbol(func20, Decl(b.js, 48, 33)) + + diff --git a/tests/baselines/reference/moduleExportAlias.types b/tests/baselines/reference/moduleExportAlias.types new file mode 100644 index 00000000000..2fbc6322955 --- /dev/null +++ b/tests/baselines/reference/moduleExportAlias.types @@ -0,0 +1,395 @@ +=== tests/cases/conformance/salsa/a.ts === + +import b = require("./b.js"); +>b : typeof b + +b.func1; +>b.func1 : () => void +>b : typeof b +>func1 : () => void + +b.func2; +>b.func2 : () => void +>b : typeof b +>func2 : () => void + +b.func3; +>b.func3 : () => void +>b : typeof b +>func3 : () => void + +b.func4; +>b.func4 : () => void +>b : typeof b +>func4 : () => void + +b.func5; +>b.func5 : () => void +>b : typeof b +>func5 : () => void + +b.func6; +>b.func6 : () => void +>b : typeof b +>func6 : () => void + +b.func7; +>b.func7 : () => void +>b : typeof b +>func7 : () => void + +b.func8; +>b.func8 : () => void +>b : typeof b +>func8 : () => void + +b.func9; +>b.func9 : () => void +>b : typeof b +>func9 : () => void + +b.func10; +>b.func10 : () => void +>b : typeof b +>func10 : () => void + +b.func11; +>b.func11 : () => void +>b : typeof b +>func11 : () => void + +b.func12; +>b.func12 : () => void +>b : typeof b +>func12 : () => void + +b.func13; +>b.func13 : () => void +>b : typeof b +>func13 : () => void + +b.func14; +>b.func14 : () => void +>b : typeof b +>func14 : () => void + +b.func15; +>b.func15 : () => void +>b : typeof b +>func15 : () => void + +b.func16; +>b.func16 : () => void +>b : typeof b +>func16 : () => void + +b.func17; +>b.func17 : () => void +>b : typeof b +>func17 : () => void + +b.func18; +>b.func18 : () => void +>b : typeof b +>func18 : () => void + +b.func19; +>b.func19 : () => void +>b : typeof b +>func19 : () => void + +b.func20; +>b.func20 : () => void +>b : typeof b +>func20 : () => void + + +=== tests/cases/conformance/salsa/b.js === +var exportsAlias = exports; +>exportsAlias : any +>exports : any + +exportsAlias.func1 = function () { }; +>exportsAlias.func1 = function () { } : () => void +>exportsAlias.func1 : any +>exportsAlias : any +>func1 : any +>function () { } : () => void + +exports.func2 = function () { }; +>exports.func2 = function () { } : () => void +>exports.func2 : any +>exports : any +>func2 : any +>function () { } : () => void + +var moduleExportsAlias = module.exports; +>moduleExportsAlias : any +>module.exports : any +>module : any +>exports : any + +moduleExportsAlias.func3 = function () { }; +>moduleExportsAlias.func3 = function () { } : () => void +>moduleExportsAlias.func3 : any +>moduleExportsAlias : any +>func3 : any +>function () { } : () => void + +module.exports.func4 = function () { }; +>module.exports.func4 = function () { } : () => void +>module.exports.func4 : any +>module.exports : any +>module : any +>exports : any +>func4 : any +>function () { } : () => void + +var multipleDeclarationAlias1 = exports = module.exports; +>multipleDeclarationAlias1 : any +>exports = module.exports : any +>exports : any +>module.exports : any +>module : any +>exports : any + +multipleDeclarationAlias1.func5 = function () { }; +>multipleDeclarationAlias1.func5 = function () { } : () => void +>multipleDeclarationAlias1.func5 : any +>multipleDeclarationAlias1 : any +>func5 : any +>function () { } : () => void + +var multipleDeclarationAlias2 = module.exports = exports; +>multipleDeclarationAlias2 : any +>module.exports = exports : any +>module.exports : any +>module : any +>exports : any +>exports : any + +multipleDeclarationAlias2.func6 = function () { }; +>multipleDeclarationAlias2.func6 = function () { } : () => void +>multipleDeclarationAlias2.func6 : any +>multipleDeclarationAlias2 : any +>func6 : any +>function () { } : () => void + +var someOtherVariable; +>someOtherVariable : any + +var multipleDeclarationAlias3 = someOtherVariable = exports; +>multipleDeclarationAlias3 : any +>someOtherVariable = exports : any +>someOtherVariable : any +>exports : any + +multipleDeclarationAlias3.func7 = function () { }; +>multipleDeclarationAlias3.func7 = function () { } : () => void +>multipleDeclarationAlias3.func7 : any +>multipleDeclarationAlias3 : any +>func7 : any +>function () { } : () => void + +var multipleDeclarationAlias4 = someOtherVariable = module.exports; +>multipleDeclarationAlias4 : any +>someOtherVariable = module.exports : any +>someOtherVariable : any +>module.exports : any +>module : any +>exports : any + +multipleDeclarationAlias4.func8 = function () { }; +>multipleDeclarationAlias4.func8 = function () { } : () => void +>multipleDeclarationAlias4.func8 : any +>multipleDeclarationAlias4 : any +>func8 : any +>function () { } : () => void + +var multipleDeclarationAlias5 = module.exports = exports = {}; +>multipleDeclarationAlias5 : {} +>module.exports = exports = {} : {} +>module.exports : any +>module : any +>exports : any +>exports = {} : {} +>exports : any +>{} : {} + +multipleDeclarationAlias5.func9 = function () { }; +>multipleDeclarationAlias5.func9 = function () { } : () => void +>multipleDeclarationAlias5.func9 : any +>multipleDeclarationAlias5 : {} +>func9 : any +>function () { } : () => void + +var multipleDeclarationAlias6 = exports = module.exports = {}; +>multipleDeclarationAlias6 : {} +>exports = module.exports = {} : {} +>exports : any +>module.exports = {} : {} +>module.exports : any +>module : any +>exports : any +>{} : {} + +multipleDeclarationAlias6.func10 = function () { }; +>multipleDeclarationAlias6.func10 = function () { } : () => void +>multipleDeclarationAlias6.func10 : any +>multipleDeclarationAlias6 : {} +>func10 : any +>function () { } : () => void + +exports = module.exports = someOtherVariable = {}; +>exports = module.exports = someOtherVariable = {} : {} +>exports : any +>module.exports = someOtherVariable = {} : {} +>module.exports : any +>module : any +>exports : any +>someOtherVariable = {} : {} +>someOtherVariable : any +>{} : {} + +exports.func11 = function () { }; +>exports.func11 = function () { } : () => void +>exports.func11 : any +>exports : any +>func11 : any +>function () { } : () => void + +module.exports.func12 = function () { }; +>module.exports.func12 = function () { } : () => void +>module.exports.func12 : any +>module.exports : any +>module : any +>exports : any +>func12 : any +>function () { } : () => void + +exports = module.exports = someOtherVariable = {}; +>exports = module.exports = someOtherVariable = {} : {} +>exports : any +>module.exports = someOtherVariable = {} : {} +>module.exports : any +>module : any +>exports : any +>someOtherVariable = {} : {} +>someOtherVariable : any +>{} : {} + +exports.func11 = function () { }; +>exports.func11 = function () { } : () => void +>exports.func11 : any +>exports : any +>func11 : any +>function () { } : () => void + +module.exports.func12 = function () { }; +>module.exports.func12 = function () { } : () => void +>module.exports.func12 : any +>module.exports : any +>module : any +>exports : any +>func12 : any +>function () { } : () => void + +exports = module.exports = {}; +>exports = module.exports = {} : {} +>exports : any +>module.exports = {} : {} +>module.exports : any +>module : any +>exports : any +>{} : {} + +exports.func13 = function () { }; +>exports.func13 = function () { } : () => void +>exports.func13 : any +>exports : any +>func13 : any +>function () { } : () => void + +module.exports.func14 = function () { }; +>module.exports.func14 = function () { } : () => void +>module.exports.func14 : any +>module.exports : any +>module : any +>exports : any +>func14 : any +>function () { } : () => void + +exports = module.exports = {}; +>exports = module.exports = {} : {} +>exports : any +>module.exports = {} : {} +>module.exports : any +>module : any +>exports : any +>{} : {} + +exports.func15 = function () { }; +>exports.func15 = function () { } : () => void +>exports.func15 : any +>exports : any +>func15 : any +>function () { } : () => void + +module.exports.func16 = function () { }; +>module.exports.func16 = function () { } : () => void +>module.exports.func16 : any +>module.exports : any +>module : any +>exports : any +>func16 : any +>function () { } : () => void + +module.exports = exports = {}; +>module.exports = exports = {} : {} +>module.exports : any +>module : any +>exports : any +>exports = {} : {} +>exports : any +>{} : {} + +exports.func17 = function () { }; +>exports.func17 = function () { } : () => void +>exports.func17 : any +>exports : any +>func17 : any +>function () { } : () => void + +module.exports.func18 = function () { }; +>module.exports.func18 = function () { } : () => void +>module.exports.func18 : any +>module.exports : any +>module : any +>exports : any +>func18 : any +>function () { } : () => void + +module.exports = {}; +>module.exports = {} : {} +>module.exports : any +>module : any +>exports : any +>{} : {} + +exports.func19 = function () { }; +>exports.func19 = function () { } : () => void +>exports.func19 : any +>exports : any +>func19 : any +>function () { } : () => void + +module.exports.func20 = function () { }; +>module.exports.func20 = function () { } : () => void +>module.exports.func20 : any +>module.exports : any +>module : any +>exports : any +>func20 : any +>function () { } : () => void + + diff --git a/tests/cases/conformance/salsa/moduleExportAlias.ts b/tests/cases/conformance/salsa/moduleExportAlias.ts new file mode 100644 index 00000000000..60220271a57 --- /dev/null +++ b/tests/cases/conformance/salsa/moduleExportAlias.ts @@ -0,0 +1,79 @@ +// @allowJS: true +// @noEmit: true + +// @filename: a.ts +import b = require("./b.js"); +b.func1; +b.func2; +b.func3; +b.func4; +b.func5; +b.func6; +b.func7; +b.func8; +b.func9; +b.func10; +b.func11; +b.func12; +b.func13; +b.func14; +b.func15; +b.func16; +b.func17; +b.func18; +b.func19; +b.func20; + + +// @filename: b.js +var exportsAlias = exports; +exportsAlias.func1 = function () { }; +exports.func2 = function () { }; + +var moduleExportsAlias = module.exports; +moduleExportsAlias.func3 = function () { }; +module.exports.func4 = function () { }; + +var multipleDeclarationAlias1 = exports = module.exports; +multipleDeclarationAlias1.func5 = function () { }; + +var multipleDeclarationAlias2 = module.exports = exports; +multipleDeclarationAlias2.func6 = function () { }; + +var someOtherVariable; +var multipleDeclarationAlias3 = someOtherVariable = exports; +multipleDeclarationAlias3.func7 = function () { }; + +var multipleDeclarationAlias4 = someOtherVariable = module.exports; +multipleDeclarationAlias4.func8 = function () { }; + +var multipleDeclarationAlias5 = module.exports = exports = {}; +multipleDeclarationAlias5.func9 = function () { }; + +var multipleDeclarationAlias6 = exports = module.exports = {}; +multipleDeclarationAlias6.func10 = function () { }; + +exports = module.exports = someOtherVariable = {}; +exports.func11 = function () { }; +module.exports.func12 = function () { }; + +exports = module.exports = someOtherVariable = {}; +exports.func11 = function () { }; +module.exports.func12 = function () { }; + +exports = module.exports = {}; +exports.func13 = function () { }; +module.exports.func14 = function () { }; + +exports = module.exports = {}; +exports.func15 = function () { }; +module.exports.func16 = function () { }; + +module.exports = exports = {}; +exports.func17 = function () { }; +module.exports.func18 = function () { }; + +module.exports = {}; +exports.func19 = function () { }; +module.exports.func20 = function () { }; + From 7e2abfca28afa936bd3f4c367f8ebf110a441054 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 21 Feb 2017 18:44:57 -0800 Subject: [PATCH 10/65] Add a string indexer to any for object literals on a .js file --- src/compiler/checker.ts | 6 +- .../jsFileCompilationShortHandProperty.types | 4 +- .../reference/jsObjectsMarkedAsOpenEnded.js | 63 +++++++++ .../jsObjectsMarkedAsOpenEnded.symbols | 76 +++++++++++ .../jsObjectsMarkedAsOpenEnded.types | 128 ++++++++++++++++++ .../untypedModuleImport_allowJs.types | 8 +- .../salsa/jsObjectsMarkedAsOpenEnded.ts | 36 +++++ 7 files changed, 313 insertions(+), 8 deletions(-) create mode 100644 tests/baselines/reference/jsObjectsMarkedAsOpenEnded.js create mode 100644 tests/baselines/reference/jsObjectsMarkedAsOpenEnded.symbols create mode 100644 tests/baselines/reference/jsObjectsMarkedAsOpenEnded.types create mode 100644 tests/cases/conformance/salsa/jsObjectsMarkedAsOpenEnded.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 12b55aa818b..512e4be870b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -240,6 +240,7 @@ namespace ts { const silentNeverSignature = createSignature(undefined, undefined, undefined, emptyArray, silentNeverType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); const enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true); + const jsObjectLiteralIndexInfo = createIndexInfo(anyType, /*isReadonly*/ false); const globals = createMap(); /** @@ -12144,6 +12145,7 @@ namespace ts { const contextualType = getApparentTypeOfContextualType(node); const contextualTypeHasPattern = contextualType && contextualType.pattern && (contextualType.pattern.kind === SyntaxKind.ObjectBindingPattern || contextualType.pattern.kind === SyntaxKind.ObjectLiteralExpression); + const isJSObjectLiteral = !contextualType && isInJavaScriptFile(node); let typeFlags: TypeFlags = 0; let patternWithComputedProperties = false; let hasComputedStringProperty = false; @@ -12281,8 +12283,8 @@ namespace ts { return createObjectLiteralType(); function createObjectLiteralType() { - const stringIndexInfo = hasComputedStringProperty ? getObjectLiteralIndexInfo(node.properties, offset, propertiesArray, IndexKind.String) : undefined; - const numberIndexInfo = hasComputedNumberProperty ? getObjectLiteralIndexInfo(node.properties, offset, propertiesArray, IndexKind.Number) : undefined; + const stringIndexInfo = isJSObjectLiteral ? jsObjectLiteralIndexInfo : hasComputedStringProperty ? getObjectLiteralIndexInfo(node.properties, offset, propertiesArray, IndexKind.String) : undefined; + const numberIndexInfo = hasComputedNumberProperty && !isJSObjectLiteral ? getObjectLiteralIndexInfo(node.properties, offset, propertiesArray, IndexKind.Number) : undefined; const result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo); const freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : TypeFlags.FreshLiteral; result.flags |= TypeFlags.ContainsObjectLiteral | freshObjectLiteralFlag | (typeFlags & TypeFlags.PropagatingFlags); diff --git a/tests/baselines/reference/jsFileCompilationShortHandProperty.types b/tests/baselines/reference/jsFileCompilationShortHandProperty.types index d6badf44909..ab8892b4661 100644 --- a/tests/baselines/reference/jsFileCompilationShortHandProperty.types +++ b/tests/baselines/reference/jsFileCompilationShortHandProperty.types @@ -1,7 +1,7 @@ === tests/cases/compiler/a.js === function foo() { ->foo : () => { a: number; b: string; } +>foo : () => { [x: string]: any; a: number; b: string; } var a = 10; >a : number @@ -12,7 +12,7 @@ function foo() { >"Hello" : "Hello" return { ->{ a, b } : { a: number; b: string; } +>{ a, b } : { [x: string]: any; a: number; b: string; } a, >a : number diff --git a/tests/baselines/reference/jsObjectsMarkedAsOpenEnded.js b/tests/baselines/reference/jsObjectsMarkedAsOpenEnded.js new file mode 100644 index 00000000000..c9bec8b56af --- /dev/null +++ b/tests/baselines/reference/jsObjectsMarkedAsOpenEnded.js @@ -0,0 +1,63 @@ +//// [tests/cases/conformance/salsa/jsObjectsMarkedAsOpenEnded.ts] //// + +//// [a.js] + +var variable = {}; +variable.a = 0; + +class C { + initializedMember = {}; + constructor() { + this.member = {}; + this.member.a = 0; + } +} + +var obj = { + property: {} +}; + +obj.property.a = 0; + +var arr = [{}]; + +function getObj() { + return {}; +} + + +//// [b.ts] +variable.a = 1; +(new C()).member.a = 1; +(new C()).initializedMember.a = 1; +obj.property.a = 1; +arr[0].a = 1; +getObj().a = 1; + + + +//// [output.js] +var variable = {}; +variable.a = 0; +var C = (function () { + function C() { + this.initializedMember = {}; + this.member = {}; + this.member.a = 0; + } + return C; +}()); +var obj = { + property: {} +}; +obj.property.a = 0; +var arr = [{}]; +function getObj() { + return {}; +} +variable.a = 1; +(new C()).member.a = 1; +(new C()).initializedMember.a = 1; +obj.property.a = 1; +arr[0].a = 1; +getObj().a = 1; diff --git a/tests/baselines/reference/jsObjectsMarkedAsOpenEnded.symbols b/tests/baselines/reference/jsObjectsMarkedAsOpenEnded.symbols new file mode 100644 index 00000000000..35a39ac6a80 --- /dev/null +++ b/tests/baselines/reference/jsObjectsMarkedAsOpenEnded.symbols @@ -0,0 +1,76 @@ +=== tests/cases/conformance/salsa/a.js === + +var variable = {}; +>variable : Symbol(variable, Decl(a.js, 1, 3)) + +variable.a = 0; +>variable : Symbol(variable, Decl(a.js, 1, 3)) + +class C { +>C : Symbol(C, Decl(a.js, 2, 15)) + + initializedMember = {}; +>initializedMember : Symbol(C.initializedMember, Decl(a.js, 4, 9)) + + constructor() { + this.member = {}; +>this.member : Symbol(C.member, Decl(a.js, 6, 19)) +>this : Symbol(C, Decl(a.js, 2, 15)) +>member : Symbol(C.member, Decl(a.js, 6, 19)) + + this.member.a = 0; +>this.member : Symbol(C.member, Decl(a.js, 6, 19)) +>this : Symbol(C, Decl(a.js, 2, 15)) +>member : Symbol(C.member, Decl(a.js, 6, 19)) + } +} + +var obj = { +>obj : Symbol(obj, Decl(a.js, 12, 3)) + + property: {} +>property : Symbol(property, Decl(a.js, 12, 11)) + +}; + +obj.property.a = 0; +>obj.property : Symbol(property, Decl(a.js, 12, 11)) +>obj : Symbol(obj, Decl(a.js, 12, 3)) +>property : Symbol(property, Decl(a.js, 12, 11)) + +var arr = [{}]; +>arr : Symbol(arr, Decl(a.js, 18, 3)) + +function getObj() { +>getObj : Symbol(getObj, Decl(a.js, 18, 15)) + + return {}; +} + + +=== tests/cases/conformance/salsa/b.ts === +variable.a = 1; +>variable : Symbol(variable, Decl(a.js, 1, 3)) + +(new C()).member.a = 1; +>(new C()).member : Symbol(C.member, Decl(a.js, 6, 19)) +>C : Symbol(C, Decl(a.js, 2, 15)) +>member : Symbol(C.member, Decl(a.js, 6, 19)) + +(new C()).initializedMember.a = 1; +>(new C()).initializedMember : Symbol(C.initializedMember, Decl(a.js, 4, 9)) +>C : Symbol(C, Decl(a.js, 2, 15)) +>initializedMember : Symbol(C.initializedMember, Decl(a.js, 4, 9)) + +obj.property.a = 1; +>obj.property : Symbol(property, Decl(a.js, 12, 11)) +>obj : Symbol(obj, Decl(a.js, 12, 3)) +>property : Symbol(property, Decl(a.js, 12, 11)) + +arr[0].a = 1; +>arr : Symbol(arr, Decl(a.js, 18, 3)) + +getObj().a = 1; +>getObj : Symbol(getObj, Decl(a.js, 18, 15)) + + diff --git a/tests/baselines/reference/jsObjectsMarkedAsOpenEnded.types b/tests/baselines/reference/jsObjectsMarkedAsOpenEnded.types new file mode 100644 index 00000000000..97f61e68a5a --- /dev/null +++ b/tests/baselines/reference/jsObjectsMarkedAsOpenEnded.types @@ -0,0 +1,128 @@ +=== tests/cases/conformance/salsa/a.js === + +var variable = {}; +>variable : { [x: string]: any; } +>{} : { [x: string]: any; } + +variable.a = 0; +>variable.a = 0 : 0 +>variable.a : any +>variable : { [x: string]: any; } +>a : any +>0 : 0 + +class C { +>C : C + + initializedMember = {}; +>initializedMember : { [x: string]: any; } +>{} : { [x: string]: any; } + + constructor() { + this.member = {}; +>this.member = {} : { [x: string]: any; } +>this.member : { [x: string]: any; } +>this : this +>member : { [x: string]: any; } +>{} : { [x: string]: any; } + + this.member.a = 0; +>this.member.a = 0 : 0 +>this.member.a : any +>this.member : { [x: string]: any; } +>this : this +>member : { [x: string]: any; } +>a : any +>0 : 0 + } +} + +var obj = { +>obj : { [x: string]: any; property: { [x: string]: any; }; } +>{ property: {}} : { [x: string]: any; property: { [x: string]: any; }; } + + property: {} +>property : { [x: string]: any; } +>{} : { [x: string]: any; } + +}; + +obj.property.a = 0; +>obj.property.a = 0 : 0 +>obj.property.a : any +>obj.property : { [x: string]: any; } +>obj : { [x: string]: any; property: { [x: string]: any; }; } +>property : { [x: string]: any; } +>a : any +>0 : 0 + +var arr = [{}]; +>arr : { [x: string]: any; }[] +>[{}] : { [x: string]: any; }[] +>{} : { [x: string]: any; } + +function getObj() { +>getObj : () => { [x: string]: any; } + + return {}; +>{} : { [x: string]: any; } +} + + +=== tests/cases/conformance/salsa/b.ts === +variable.a = 1; +>variable.a = 1 : 1 +>variable.a : any +>variable : { [x: string]: any; } +>a : any +>1 : 1 + +(new C()).member.a = 1; +>(new C()).member.a = 1 : 1 +>(new C()).member.a : any +>(new C()).member : { [x: string]: any; } +>(new C()) : C +>new C() : C +>C : typeof C +>member : { [x: string]: any; } +>a : any +>1 : 1 + +(new C()).initializedMember.a = 1; +>(new C()).initializedMember.a = 1 : 1 +>(new C()).initializedMember.a : any +>(new C()).initializedMember : { [x: string]: any; } +>(new C()) : C +>new C() : C +>C : typeof C +>initializedMember : { [x: string]: any; } +>a : any +>1 : 1 + +obj.property.a = 1; +>obj.property.a = 1 : 1 +>obj.property.a : any +>obj.property : { [x: string]: any; } +>obj : { [x: string]: any; property: { [x: string]: any; }; } +>property : { [x: string]: any; } +>a : any +>1 : 1 + +arr[0].a = 1; +>arr[0].a = 1 : 1 +>arr[0].a : any +>arr[0] : { [x: string]: any; } +>arr : { [x: string]: any; }[] +>0 : 0 +>a : any +>1 : 1 + +getObj().a = 1; +>getObj().a = 1 : 1 +>getObj().a : any +>getObj() : { [x: string]: any; } +>getObj : () => { [x: string]: any; } +>a : any +>1 : 1 + + diff --git a/tests/baselines/reference/untypedModuleImport_allowJs.types b/tests/baselines/reference/untypedModuleImport_allowJs.types index 5a34fdcb646..108ba60ccb3 100644 --- a/tests/baselines/reference/untypedModuleImport_allowJs.types +++ b/tests/baselines/reference/untypedModuleImport_allowJs.types @@ -1,22 +1,22 @@ === /a.ts === import foo from "foo"; ->foo : { bar(): number; } +>foo : { [x: string]: any; bar(): number; } foo.bar(); >foo.bar() : number >foo.bar : () => number ->foo : { bar(): number; } +>foo : { [x: string]: any; bar(): number; } >bar : () => number === /node_modules/foo/index.js === // Same as untypedModuleImport.ts but with --allowJs, so the package will actually be typed. exports.default = { bar() { return 0; } } ->exports.default = { bar() { return 0; } } : { bar(): number; } +>exports.default = { bar() { return 0; } } : { [x: string]: any; bar(): number; } >exports.default : any >exports : any >default : any ->{ bar() { return 0; } } : { bar(): number; } +>{ bar() { return 0; } } : { [x: string]: any; bar(): number; } >bar : () => number >0 : 0 diff --git a/tests/cases/conformance/salsa/jsObjectsMarkedAsOpenEnded.ts b/tests/cases/conformance/salsa/jsObjectsMarkedAsOpenEnded.ts new file mode 100644 index 00000000000..52b27641f0d --- /dev/null +++ b/tests/cases/conformance/salsa/jsObjectsMarkedAsOpenEnded.ts @@ -0,0 +1,36 @@ +// @out: output.js +// @allowJs: true + +// @filename: a.js +var variable = {}; +variable.a = 0; + +class C { + initializedMember = {}; + constructor() { + this.member = {}; + this.member.a = 0; + } +} + +var obj = { + property: {} +}; + +obj.property.a = 0; + +var arr = [{}]; + +function getObj() { + return {}; +} + + +// @filename: b.ts +variable.a = 1; +(new C()).member.a = 1; +(new C()).initializedMember.a = 1; +obj.property.a = 1; +arr[0].a = 1; +getObj().a = 1; + From 168d367b5e740ae1896c01a26d6bb3d2af038566 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 22 Feb 2017 19:16:55 -0800 Subject: [PATCH 11/65] Contextually type 'this' in accessors of object literals --- src/compiler/checker.ts | 97 +++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 47 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9fb71884c51..69c294e97c2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8983,11 +8983,19 @@ namespace ts { return regularNew; } + function getWidenedProperty(prop: Symbol): Symbol { + const original = getTypeOfSymbol(prop); + const widened = getWidenedType(original); + return widened === original ? prop : createSymbolWithType(prop, widened); + } + function getWidenedTypeOfObjectLiteral(type: Type): Type { - const members = transformTypeOfMembers(type, prop => { - const widened = getWidenedType(prop); - return prop === widened ? prop : widened; - }); + const members = createMap(); + for (let prop of getPropertiesOfObjectType(type)) { + // Since get accessors already widen their return value there is no need to + // widen accessor based properties here. + members.set(prop.name, prop.flags & SymbolFlags.Property ? getWidenedProperty(prop) : prop); + }; const stringIndexInfo = getIndexInfoOfType(type, IndexKind.String); const numberIndexInfo = getIndexInfoOfType(type, IndexKind.Number); return createAnonymousType(type.symbol, members, emptyArray, emptyArray, @@ -11471,7 +11479,9 @@ namespace ts { } function getContainingObjectLiteral(func: FunctionLikeDeclaration) { - return func.kind === SyntaxKind.MethodDeclaration && func.parent.kind === SyntaxKind.ObjectLiteralExpression ? func.parent : + return (func.kind === SyntaxKind.MethodDeclaration || + func.kind === SyntaxKind.GetAccessor || + func.kind === SyntaxKind.SetAccessor) && func.parent.kind === SyntaxKind.ObjectLiteralExpression ? func.parent : func.kind === SyntaxKind.FunctionExpression && func.parent.kind === SyntaxKind.PropertyAssignment ? func.parent.parent : undefined; } @@ -11487,7 +11497,10 @@ namespace ts { } function getContextualThisParameterType(func: FunctionLikeDeclaration): Type { - if (isContextSensitiveFunctionOrObjectLiteralMethod(func) && func.kind !== SyntaxKind.ArrowFunction) { + if (func.kind === SyntaxKind.ArrowFunction) { + return undefined; + } + if (isContextSensitiveFunctionOrObjectLiteralMethod(func)) { const contextualSignature = getContextualSignature(func); if (contextualSignature) { const thisParameter = contextualSignature.thisParameter; @@ -11495,36 +11508,36 @@ namespace ts { return getTypeOfSymbol(thisParameter); } } - const containingLiteral = getContainingObjectLiteral(func); - if (containingLiteral) { - // We have an object literal method. Check if the containing object literal has a contextual type - // and if that contextual type is or includes a ThisType. If so, T is the contextual type for - // 'this'. We continue looking in any directly enclosing object literals. - let objectLiteral = containingLiteral; - while (true) { - const type = getApparentTypeOfContextualType(objectLiteral); - if (type) { - const thisType = getThisTypeFromContextualType(type); - if (thisType) { - return thisType; - } + } + const containingLiteral = getContainingObjectLiteral(func); + if (containingLiteral) { + // We have an object literal method. Check if the containing object literal has a contextual type + // and if that contextual type is or includes a ThisType. If so, T is the contextual type for + // 'this'. We continue looking in any directly enclosing object literals. + let objectLiteral = containingLiteral; + while (true) { + const type = getApparentTypeOfContextualType(objectLiteral); + if (type) { + const thisType = getThisTypeFromContextualType(type); + if (thisType) { + return thisType; } - if (objectLiteral.parent.kind !== SyntaxKind.PropertyAssignment) { - break; - } - objectLiteral = objectLiteral.parent.parent; } - // There was no contextual ThisType for the containing object literal, so the contextual type - // for 'this' is the type of the object literal itself. - return checkExpressionCached(containingLiteral); + if (objectLiteral.parent.kind !== SyntaxKind.PropertyAssignment) { + break; + } + objectLiteral = objectLiteral.parent.parent; } - // In an assignment of the form 'obj.xxx = function(...)' or 'obj[xxx] = function(...)', the - // contextual type for 'this' is 'obj'. - if (func.parent.kind === SyntaxKind.BinaryExpression && (func.parent).operatorToken.kind === SyntaxKind.EqualsToken) { - const target = (func.parent).left; - if (target.kind === SyntaxKind.PropertyAccessExpression || target.kind === SyntaxKind.ElementAccessExpression) { - return checkExpressionCached((target).expression); - } + // There was no contextual ThisType for the containing object literal, so the contextual type + // for 'this' is the type of the object literal itself. + return checkExpressionCached(containingLiteral); + } + // In an assignment of the form 'obj.xxx = function(...)' or 'obj[xxx] = function(...)', the + // contextual type for 'this' is 'obj'. + if (func.parent.kind === SyntaxKind.BinaryExpression && (func.parent).operatorToken.kind === SyntaxKind.EqualsToken) { + const target = (func.parent).left; + if (target.kind === SyntaxKind.PropertyAccessExpression || target.kind === SyntaxKind.ElementAccessExpression) { + return checkExpressionCached((target).expression); } } return undefined; @@ -12287,7 +12300,7 @@ namespace ts { // A set accessor declaration is processed in the same manner // as an ordinary function declaration with a single parameter and a Void return type. Debug.assert(memberDecl.kind === SyntaxKind.GetAccessor || memberDecl.kind === SyntaxKind.SetAccessor); - checkAccessorDeclaration(memberDecl); + checkNodeDeferred(memberDecl); } if (hasDynamicName(memberDecl)) { @@ -16942,13 +16955,8 @@ namespace ts { checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnType); } } - if (node.parent.kind !== SyntaxKind.ObjectLiteralExpression) { - checkSourceElement(node.body); - registerForUnusedIdentifiersCheck(node); - } - else { - checkNodeDeferred(node); - } + checkSourceElement(node.body); + registerForUnusedIdentifiersCheck(node); } function checkAccessorDeclarationTypesIdentical(first: AccessorDeclaration, second: AccessorDeclaration, getAnnotatedType: (a: AccessorDeclaration) => Type, message: DiagnosticMessage) { @@ -16959,11 +16967,6 @@ namespace ts { } } - function checkAccessorDeferred(node: AccessorDeclaration) { - checkSourceElement(node.body); - registerForUnusedIdentifiersCheck(node); - } - function checkMissingDeclaration(node: Node) { checkDecorators(node); } @@ -20630,7 +20633,7 @@ namespace ts { break; case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - checkAccessorDeferred(node); + checkAccessorDeclaration(node); break; case SyntaxKind.ClassExpression: checkClassExpressionDeferred(node); From c2d8a593b9eb9642d7a2bc57d4cd49bdd85c206e Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 22 Feb 2017 19:18:53 -0800 Subject: [PATCH 12/65] Accept new baselines --- .../commentsOnObjectLiteral3.symbols | 7 +++++ .../reference/commentsOnObjectLiteral3.types | 26 +++++++++---------- ...declFileObjectLiteralWithAccessors.symbols | 3 +++ .../declFileObjectLiteralWithAccessors.types | 6 ++--- ...eclFileObjectLiteralWithOnlySetter.symbols | 3 +++ .../declFileObjectLiteralWithOnlySetter.types | 6 ++--- ...iationAssignmentWithIndexingOnLHS3.symbols | 7 +++++ ...ntiationAssignmentWithIndexingOnLHS3.types | 12 ++++----- .../thisTypeInAccessorsNegative.errors.txt | 5 +--- 9 files changed, 46 insertions(+), 29 deletions(-) diff --git a/tests/baselines/reference/commentsOnObjectLiteral3.symbols b/tests/baselines/reference/commentsOnObjectLiteral3.symbols index 3d58fe2d6d7..34b4c706b42 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(v, 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(v, 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 4053e7e3f89..b869e961401 100644 --- a/tests/baselines/reference/commentsOnObjectLiteral3.types +++ b/tests/baselines/reference/commentsOnObjectLiteral3.types @@ -1,8 +1,8 @@ === tests/cases/compiler/commentsOnObjectLiteral3.ts === var v = { ->v : { prop: number; func: () => void; func1(): void; a: any; } ->{ //property prop: 1 /* multiple trailing comments */ /*trailing comments*/, //property func: function () { }, //PropertyName + CallSignature func1() { }, //getter get a() { return this.prop; } /*trailing 1*/, //setter set a(value) { this.prop = value; } // trailing 2} : { prop: number; func: () => void; func1(): void; a: any; } +>v : { prop: number; func: () => void; func1(): void; a: number; } +>{ //property prop: 1 /* multiple trailing comments */ /*trailing comments*/, //property func: function () { }, //PropertyName + CallSignature func1() { }, //getter get a() { return this.prop; } /*trailing 1*/, //setter set a(value) { this.prop = value; } // trailing 2} : { prop: number; func: () => void; func1(): void; a: number; } //property prop: 1 /* multiple trailing comments */ /*trailing comments*/, @@ -21,25 +21,25 @@ var v = { //getter get a() { ->a : any +>a : number return this.prop; ->this.prop : any ->this : any ->prop : any +>this.prop : number +>this : { prop: number; func: () => void; func1(): void; a: number; } +>prop : number } /*trailing 1*/, //setter set a(value) { ->a : any ->value : any +>a : number +>value : number this.prop = value; ->this.prop = value : any ->this.prop : any ->this : any ->prop : any ->value : any +>this.prop = value : number +>this.prop : number +>this : { prop: number; func: () => void; func1(): void; a: number; } +>prop : number +>value : number } // trailing 2 }; diff --git a/tests/baselines/reference/declFileObjectLiteralWithAccessors.symbols b/tests/baselines/reference/declFileObjectLiteralWithAccessors.symbols index 862b0b3781e..df94b262c74 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(__object, 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 389b88de565..1c36f321118 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..9dd2461b871 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(__object, 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 2f15818e0f2..bf62561f57d 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/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.symbols b/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.symbols index dbd5aa150dc..785a5654681 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(object, 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(object, 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 32e5b33e411..77026be2795 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/thisTypeInAccessorsNegative.errors.txt b/tests/baselines/reference/thisTypeInAccessorsNegative.errors.txt index 5396f1f4316..eb2c93e7845 100644 --- a/tests/baselines/reference/thisTypeInAccessorsNegative.errors.txt +++ b/tests/baselines/reference/thisTypeInAccessorsNegative.errors.txt @@ -1,9 +1,8 @@ tests/cases/conformance/types/thisType/thisTypeInAccessorsNegative.ts(10,9): error TS2682: 'get' and 'set' accessor must have the same 'this' type. tests/cases/conformance/types/thisType/thisTypeInAccessorsNegative.ts(11,9): error TS2682: 'get' and 'set' accessor must have the same 'this' type. -tests/cases/conformance/types/thisType/thisTypeInAccessorsNegative.ts(16,22): error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation. -==== tests/cases/conformance/types/thisType/thisTypeInAccessorsNegative.ts (3 errors) ==== +==== tests/cases/conformance/types/thisType/thisTypeInAccessorsNegative.ts (2 errors) ==== interface Foo { n: number; x: number; @@ -24,7 +23,5 @@ tests/cases/conformance/types/thisType/thisTypeInAccessorsNegative.ts(16,22): er n: 16, // there is no contextual this type from an Foo.x. get x() { return this.n; } - ~~~~ -!!! error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation. } \ No newline at end of file From ec292c92e292c0747cda0002445caab76de9e627 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 22 Feb 2017 19:25:19 -0800 Subject: [PATCH 13/65] Update test --- .../baselines/reference/thisTypeInAccessorsNegative.errors.txt | 1 - tests/baselines/reference/thisTypeInAccessorsNegative.js | 2 -- .../conformance/types/thisType/thisTypeInAccessorsNegative.ts | 1 - 3 files changed, 4 deletions(-) diff --git a/tests/baselines/reference/thisTypeInAccessorsNegative.errors.txt b/tests/baselines/reference/thisTypeInAccessorsNegative.errors.txt index eb2c93e7845..cd609673723 100644 --- a/tests/baselines/reference/thisTypeInAccessorsNegative.errors.txt +++ b/tests/baselines/reference/thisTypeInAccessorsNegative.errors.txt @@ -21,7 +21,6 @@ tests/cases/conformance/types/thisType/thisTypeInAccessorsNegative.ts(11,9): err } const contextual: Foo = { n: 16, - // there is no contextual this type from an Foo.x. get x() { return this.n; } } \ No newline at end of file diff --git a/tests/baselines/reference/thisTypeInAccessorsNegative.js b/tests/baselines/reference/thisTypeInAccessorsNegative.js index 4d0826232f4..92e18f163c3 100644 --- a/tests/baselines/reference/thisTypeInAccessorsNegative.js +++ b/tests/baselines/reference/thisTypeInAccessorsNegative.js @@ -13,7 +13,6 @@ const mismatch = { } const contextual: Foo = { n: 16, - // there is no contextual this type from an Foo.x. get x() { return this.n; } } @@ -26,6 +25,5 @@ var mismatch = { }; var contextual = { n: 16, - // there is no contextual this type from an Foo.x. get x() { return this.n; } }; diff --git a/tests/cases/conformance/types/thisType/thisTypeInAccessorsNegative.ts b/tests/cases/conformance/types/thisType/thisTypeInAccessorsNegative.ts index 69ff4175a92..67b7576a4b5 100644 --- a/tests/cases/conformance/types/thisType/thisTypeInAccessorsNegative.ts +++ b/tests/cases/conformance/types/thisType/thisTypeInAccessorsNegative.ts @@ -15,6 +15,5 @@ const mismatch = { } const contextual: Foo = { n: 16, - // there is no contextual this type from an Foo.x. get x() { return this.n; } } From 9b6b6cc289a6afaeaba3ad6cb8310ad73ff62e80 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 22 Feb 2017 19:32:34 -0800 Subject: [PATCH 14/65] 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 69c294e97c2..8c1a91d203d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8991,7 +8991,7 @@ namespace ts { function getWidenedTypeOfObjectLiteral(type: Type): Type { const members = createMap(); - for (let prop of getPropertiesOfObjectType(type)) { + for (const prop of getPropertiesOfObjectType(type)) { // Since get accessors already widen their return value there is no need to // widen accessor based properties here. members.set(prop.name, prop.flags & SymbolFlags.Property ? getWidenedProperty(prop) : prop); From 02ccd911590e7e0f67dbaa54e76d8cff72b2d56f Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Thu, 23 Feb 2017 15:20:08 -0800 Subject: [PATCH 15/65] Infer class properties from methods and not just constructors --- src/compiler/binder.ts | 42 ++-- src/compiler/checker.ts | 48 ++-- .../inferringClassMembersFromAssignments.js | 150 +++++++++++ ...ferringClassMembersFromAssignments.symbols | 198 +++++++++++++++ ...inferringClassMembersFromAssignments.types | 234 ++++++++++++++++++ .../inferringClassMembersFromAssignments.ts | 79 ++++++ 6 files changed, 718 insertions(+), 33 deletions(-) create mode 100644 tests/baselines/reference/inferringClassMembersFromAssignments.js create mode 100644 tests/baselines/reference/inferringClassMembersFromAssignments.symbols create mode 100644 tests/baselines/reference/inferringClassMembersFromAssignments.types create mode 100644 tests/cases/conformance/salsa/inferringClassMembersFromAssignments.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 51830c50bfe..2fc7317884d 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2238,23 +2238,31 @@ namespace ts { function bindThisPropertyAssignment(node: BinaryExpression) { Debug.assert(isInJavaScriptFile(node)); - // Declare a 'member' if the container is an ES5 class or ES6 constructor - if (container.kind === SyntaxKind.FunctionDeclaration || container.kind === SyntaxKind.FunctionExpression) { - container.symbol.members = container.symbol.members || createMap(); - // It's acceptable for multiple 'this' assignments of the same identifier to occur - declareSymbol(container.symbol.members, container.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property); - } - else if (container.kind === SyntaxKind.Constructor) { - // this.foo assignment in a JavaScript class - // Bind this property to the containing class - const saveContainer = container; - container = container.parent; - const symbol = bindPropertyOrMethodOrAccessor(node, SymbolFlags.Property, SymbolFlags.None); - if (symbol) { - // constructor-declared symbols can be overwritten by subsequent method declarations - (symbol as Symbol).isReplaceableByMethod = true; - } - container = saveContainer; + switch (container.kind) { + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + // Declare a 'member' if the container is an ES5 class or ES6 constructor + container.symbol.members = container.symbol.members || createMap(); + // It's acceptable for multiple 'this' assignments of the same identifier to occur + declareSymbol(container.symbol.members, container.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property); + break; + + case SyntaxKind.Constructor: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + // this.foo assignment in a JavaScript class + // Bind this property to the containing class + const containingClass = container.parent; + const symbol = hasModifier(container, ModifierFlags.Static) + ? declareSymbol(containingClass.symbol.exports, containingClass.symbol, node, SymbolFlags.Property, SymbolFlags.None) + : declareSymbol(containingClass.symbol.members, containingClass.symbol, node, SymbolFlags.Property, SymbolFlags.None); + + if (symbol) { + // symbols declared through 'this' property assignements can be overwritten by subsequent method declarations + (symbol as Symbol).isReplaceableByMethod = true; + } + break; } } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 83fea11c993..93973fe71a8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3472,25 +3472,41 @@ namespace ts { return undefined; } - // Return the inferred type for a variable, parameter, or property declaration - function getTypeForJSSpecialPropertyDeclaration(declaration: Declaration): Type { - const expression = declaration.kind === SyntaxKind.BinaryExpression ? declaration : - declaration.kind === SyntaxKind.PropertyAccessExpression ? getAncestor(declaration, SyntaxKind.BinaryExpression) : - undefined; + function getWidendedTypeFromJSSpecialPropetyDeclarations(symbol: Symbol) { + const types: Type[] = []; + let definedInConstructor = false; + let definedInMethod = false; + for (const declaration of symbol.declarations) { + const expression = declaration.kind === SyntaxKind.BinaryExpression ? declaration : + declaration.kind === SyntaxKind.PropertyAccessExpression ? getAncestor(declaration, SyntaxKind.BinaryExpression) : + undefined; - if (!expression) { - return unknownType; - } - - if (expression.flags & NodeFlags.JavaScriptFile) { - // If there is a JSDoc type, use it - const type = getTypeForDeclarationFromJSDocComment(expression.parent); - if (type && type !== unknownType) { - return getWidenedType(type); + if (!expression) { + return unknownType; } + + if (isPropertyAccessExpression(expression.left) && expression.left.expression.kind === SyntaxKind.ThisKeyword) { + if (getThisContainer(expression, /*includeArrowFunctions*/ false).kind === SyntaxKind.Constructor) { + definedInConstructor = true; + } + else { + definedInMethod = true; + } + } + + if (expression.flags & NodeFlags.JavaScriptFile) { + // If there is a JSDoc type, use it + const type = getTypeForDeclarationFromJSDocComment(expression.parent); + if (type && type !== unknownType) { + types.push(getWidenedType(type)); + continue; + } + } + + types.push(getWidenedLiteralType(checkExpressionCached(expression.right))); } - return getWidenedLiteralType(checkExpressionCached(expression.right)); + return getWidenedType(addOptionality(getUnionType(types, /*subtypeReduction*/ true), definedInMethod && !definedInConstructor)); } // Return the type implied by a binding pattern element. This is the type of the initializer of the element if @@ -3647,7 +3663,7 @@ namespace ts { // * className.prototype.method = expr if (declaration.kind === SyntaxKind.BinaryExpression || declaration.kind === SyntaxKind.PropertyAccessExpression && declaration.parent.kind === SyntaxKind.BinaryExpression) { - type = getWidenedType(getUnionType(map(symbol.declarations, getTypeForJSSpecialPropertyDeclaration), /*subtypeReduction*/ true)); + type = getWidendedTypeFromJSSpecialPropetyDeclarations(symbol); } else { type = getWidenedTypeForVariableLikeDeclaration(declaration, /*reportErrors*/ true); diff --git a/tests/baselines/reference/inferringClassMembersFromAssignments.js b/tests/baselines/reference/inferringClassMembersFromAssignments.js new file mode 100644 index 00000000000..6513a3b03a6 --- /dev/null +++ b/tests/baselines/reference/inferringClassMembersFromAssignments.js @@ -0,0 +1,150 @@ +//// [tests/cases/conformance/salsa/inferringClassMembersFromAssignments.ts] //// + +//// [a.js] + +class C { + constructor() { + if (Math.random()) { + this.inConstructor = 0; + } + else { + this.inConstructor = "string" + } + } + method() { + if (Math.random()) { + this.inMethod = 0; + } + else { + this.inMethod = "string" + } + } + get() { + if (Math.random()) { + this.inGetter = 0; + } + else { + this.inGetter = "string" + } + } + set() { + if (Math.random()) { + this.inSetter = 0; + } + else { + this.inSetter = "string" + } + } + static method() { + if (Math.random()) { + this.inStaticMethod = 0; + } + else { + this.inStaticMethod = "string" + } + } + static get() { + if (Math.random()) { + this.inStaticGetter = 0; + } + else { + this.inStaticGetter = "string" + } + } + static set() { + if (Math.random()) { + this.inStaticSetter = 0; + } + else { + this.inStaticSetter = "string" + } + } +} + +//// [b.ts] +var c = new C(); + +var stringOrNumber: string | number; +var stringOrNumber = c.inConstructor; + +var stringOrNumberOrUndefined: string | number | undefined; + +var stringOrNumberOrUndefined = c.inMethod; +var stringOrNumberOrUndefined = c.inGetter; +var stringOrNumberOrUndefined = c.inSetter; + +var stringOrNumberOrUndefined = C.inStaticMethod; +var stringOrNumberOrUndefined = C.inStaticGetter; +var stringOrNumberOrUndefined = C.inStaticSetter; + + +//// [output.js] +var C = (function () { + function C() { + if (Math.random()) { + this.inConstructor = 0; + } + else { + this.inConstructor = "string"; + } + } + C.prototype.method = function () { + if (Math.random()) { + this.inMethod = 0; + } + else { + this.inMethod = "string"; + } + }; + C.prototype.get = function () { + if (Math.random()) { + this.inGetter = 0; + } + else { + this.inGetter = "string"; + } + }; + C.prototype.set = function () { + if (Math.random()) { + this.inSetter = 0; + } + else { + this.inSetter = "string"; + } + }; + C.method = function () { + if (Math.random()) { + this.inStaticMethod = 0; + } + else { + this.inStaticMethod = "string"; + } + }; + C.get = function () { + if (Math.random()) { + this.inStaticGetter = 0; + } + else { + this.inStaticGetter = "string"; + } + }; + C.set = function () { + if (Math.random()) { + this.inStaticSetter = 0; + } + else { + this.inStaticSetter = "string"; + } + }; + return C; +}()); +var c = new C(); +var stringOrNumber; +var stringOrNumber = c.inConstructor; +var stringOrNumberOrUndefined; +var stringOrNumberOrUndefined = c.inMethod; +var stringOrNumberOrUndefined = c.inGetter; +var stringOrNumberOrUndefined = c.inSetter; +var stringOrNumberOrUndefined = C.inStaticMethod; +var stringOrNumberOrUndefined = C.inStaticGetter; +var stringOrNumberOrUndefined = C.inStaticSetter; diff --git a/tests/baselines/reference/inferringClassMembersFromAssignments.symbols b/tests/baselines/reference/inferringClassMembersFromAssignments.symbols new file mode 100644 index 00000000000..d96d4ff359f --- /dev/null +++ b/tests/baselines/reference/inferringClassMembersFromAssignments.symbols @@ -0,0 +1,198 @@ +=== tests/cases/conformance/salsa/a.js === + +class C { +>C : Symbol(C, Decl(a.js, 0, 0)) + + constructor() { + if (Math.random()) { +>Math.random : Symbol(Math.random, Decl(lib.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.d.ts, --, --)) + + this.inConstructor = 0; +>this.inConstructor : Symbol(C.inConstructor, Decl(a.js, 3, 28), Decl(a.js, 6, 14)) +>this : Symbol(C, Decl(a.js, 0, 0)) +>inConstructor : Symbol(C.inConstructor, Decl(a.js, 3, 28), Decl(a.js, 6, 14)) + } + else { + this.inConstructor = "string" +>this.inConstructor : Symbol(C.inConstructor, Decl(a.js, 3, 28), Decl(a.js, 6, 14)) +>this : Symbol(C, Decl(a.js, 0, 0)) +>inConstructor : Symbol(C.inConstructor, Decl(a.js, 3, 28), Decl(a.js, 6, 14)) + } + } + method() { +>method : Symbol(C.method, Decl(a.js, 9, 5)) + + if (Math.random()) { +>Math.random : Symbol(Math.random, Decl(lib.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.d.ts, --, --)) + + this.inMethod = 0; +>this.inMethod : Symbol(C.inMethod, Decl(a.js, 11, 28), Decl(a.js, 14, 14)) +>this : Symbol(C, Decl(a.js, 0, 0)) +>inMethod : Symbol(C.inMethod, Decl(a.js, 11, 28), Decl(a.js, 14, 14)) + } + else { + this.inMethod = "string" +>this.inMethod : Symbol(C.inMethod, Decl(a.js, 11, 28), Decl(a.js, 14, 14)) +>this : Symbol(C, Decl(a.js, 0, 0)) +>inMethod : Symbol(C.inMethod, Decl(a.js, 11, 28), Decl(a.js, 14, 14)) + } + } + get() { +>get : Symbol(C.get, Decl(a.js, 17, 5)) + + if (Math.random()) { +>Math.random : Symbol(Math.random, Decl(lib.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.d.ts, --, --)) + + this.inGetter = 0; +>this.inGetter : Symbol(C.inGetter, Decl(a.js, 19, 28), Decl(a.js, 22, 14)) +>this : Symbol(C, Decl(a.js, 0, 0)) +>inGetter : Symbol(C.inGetter, Decl(a.js, 19, 28), Decl(a.js, 22, 14)) + } + else { + this.inGetter = "string" +>this.inGetter : Symbol(C.inGetter, Decl(a.js, 19, 28), Decl(a.js, 22, 14)) +>this : Symbol(C, Decl(a.js, 0, 0)) +>inGetter : Symbol(C.inGetter, Decl(a.js, 19, 28), Decl(a.js, 22, 14)) + } + } + set() { +>set : Symbol(C.set, Decl(a.js, 25, 5)) + + if (Math.random()) { +>Math.random : Symbol(Math.random, Decl(lib.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.d.ts, --, --)) + + this.inSetter = 0; +>this.inSetter : Symbol(C.inSetter, Decl(a.js, 27, 28), Decl(a.js, 30, 14)) +>this : Symbol(C, Decl(a.js, 0, 0)) +>inSetter : Symbol(C.inSetter, Decl(a.js, 27, 28), Decl(a.js, 30, 14)) + } + else { + this.inSetter = "string" +>this.inSetter : Symbol(C.inSetter, Decl(a.js, 27, 28), Decl(a.js, 30, 14)) +>this : Symbol(C, Decl(a.js, 0, 0)) +>inSetter : Symbol(C.inSetter, Decl(a.js, 27, 28), Decl(a.js, 30, 14)) + } + } + static method() { +>method : Symbol(C.method, Decl(a.js, 33, 5)) + + if (Math.random()) { +>Math.random : Symbol(Math.random, Decl(lib.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.d.ts, --, --)) + + this.inStaticMethod = 0; +>this.inStaticMethod : Symbol(C.inStaticMethod, Decl(a.js, 35, 28), Decl(a.js, 38, 14)) +>this : Symbol(C, Decl(a.js, 0, 0)) +>inStaticMethod : Symbol(C.inStaticMethod, Decl(a.js, 35, 28), Decl(a.js, 38, 14)) + } + else { + this.inStaticMethod = "string" +>this.inStaticMethod : Symbol(C.inStaticMethod, Decl(a.js, 35, 28), Decl(a.js, 38, 14)) +>this : Symbol(C, Decl(a.js, 0, 0)) +>inStaticMethod : Symbol(C.inStaticMethod, Decl(a.js, 35, 28), Decl(a.js, 38, 14)) + } + } + static get() { +>get : Symbol(C.get, Decl(a.js, 41, 5)) + + if (Math.random()) { +>Math.random : Symbol(Math.random, Decl(lib.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.d.ts, --, --)) + + this.inStaticGetter = 0; +>this.inStaticGetter : Symbol(C.inStaticGetter, Decl(a.js, 43, 28), Decl(a.js, 46, 14)) +>this : Symbol(C, Decl(a.js, 0, 0)) +>inStaticGetter : Symbol(C.inStaticGetter, Decl(a.js, 43, 28), Decl(a.js, 46, 14)) + } + else { + this.inStaticGetter = "string" +>this.inStaticGetter : Symbol(C.inStaticGetter, Decl(a.js, 43, 28), Decl(a.js, 46, 14)) +>this : Symbol(C, Decl(a.js, 0, 0)) +>inStaticGetter : Symbol(C.inStaticGetter, Decl(a.js, 43, 28), Decl(a.js, 46, 14)) + } + } + static set() { +>set : Symbol(C.set, Decl(a.js, 49, 5)) + + if (Math.random()) { +>Math.random : Symbol(Math.random, Decl(lib.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.d.ts, --, --)) + + this.inStaticSetter = 0; +>this.inStaticSetter : Symbol(C.inStaticSetter, Decl(a.js, 51, 28), Decl(a.js, 54, 14)) +>this : Symbol(C, Decl(a.js, 0, 0)) +>inStaticSetter : Symbol(C.inStaticSetter, Decl(a.js, 51, 28), Decl(a.js, 54, 14)) + } + else { + this.inStaticSetter = "string" +>this.inStaticSetter : Symbol(C.inStaticSetter, Decl(a.js, 51, 28), Decl(a.js, 54, 14)) +>this : Symbol(C, Decl(a.js, 0, 0)) +>inStaticSetter : Symbol(C.inStaticSetter, Decl(a.js, 51, 28), Decl(a.js, 54, 14)) + } + } +} + +=== tests/cases/conformance/salsa/b.ts === +var c = new C(); +>c : Symbol(c, Decl(b.ts, 0, 3)) +>C : Symbol(C, Decl(a.js, 0, 0)) + +var stringOrNumber: string | number; +>stringOrNumber : Symbol(stringOrNumber, Decl(b.ts, 2, 3), Decl(b.ts, 3, 3)) + +var stringOrNumber = c.inConstructor; +>stringOrNumber : Symbol(stringOrNumber, Decl(b.ts, 2, 3), Decl(b.ts, 3, 3)) +>c.inConstructor : Symbol(C.inConstructor, Decl(a.js, 3, 28), Decl(a.js, 6, 14)) +>c : Symbol(c, Decl(b.ts, 0, 3)) +>inConstructor : Symbol(C.inConstructor, Decl(a.js, 3, 28), Decl(a.js, 6, 14)) + +var stringOrNumberOrUndefined: string | number | undefined; +>stringOrNumberOrUndefined : Symbol(stringOrNumberOrUndefined, Decl(b.ts, 5, 3), Decl(b.ts, 7, 3), Decl(b.ts, 8, 3), Decl(b.ts, 9, 3), Decl(b.ts, 11, 3), Decl(b.ts, 12, 3), Decl(b.ts, 13, 3)) + +var stringOrNumberOrUndefined = c.inMethod; +>stringOrNumberOrUndefined : Symbol(stringOrNumberOrUndefined, Decl(b.ts, 5, 3), Decl(b.ts, 7, 3), Decl(b.ts, 8, 3), Decl(b.ts, 9, 3), Decl(b.ts, 11, 3), Decl(b.ts, 12, 3), Decl(b.ts, 13, 3)) +>c.inMethod : Symbol(C.inMethod, Decl(a.js, 11, 28), Decl(a.js, 14, 14)) +>c : Symbol(c, Decl(b.ts, 0, 3)) +>inMethod : Symbol(C.inMethod, Decl(a.js, 11, 28), Decl(a.js, 14, 14)) + +var stringOrNumberOrUndefined = c.inGetter; +>stringOrNumberOrUndefined : Symbol(stringOrNumberOrUndefined, Decl(b.ts, 5, 3), Decl(b.ts, 7, 3), Decl(b.ts, 8, 3), Decl(b.ts, 9, 3), Decl(b.ts, 11, 3), Decl(b.ts, 12, 3), Decl(b.ts, 13, 3)) +>c.inGetter : Symbol(C.inGetter, Decl(a.js, 19, 28), Decl(a.js, 22, 14)) +>c : Symbol(c, Decl(b.ts, 0, 3)) +>inGetter : Symbol(C.inGetter, Decl(a.js, 19, 28), Decl(a.js, 22, 14)) + +var stringOrNumberOrUndefined = c.inSetter; +>stringOrNumberOrUndefined : Symbol(stringOrNumberOrUndefined, Decl(b.ts, 5, 3), Decl(b.ts, 7, 3), Decl(b.ts, 8, 3), Decl(b.ts, 9, 3), Decl(b.ts, 11, 3), Decl(b.ts, 12, 3), Decl(b.ts, 13, 3)) +>c.inSetter : Symbol(C.inSetter, Decl(a.js, 27, 28), Decl(a.js, 30, 14)) +>c : Symbol(c, Decl(b.ts, 0, 3)) +>inSetter : Symbol(C.inSetter, Decl(a.js, 27, 28), Decl(a.js, 30, 14)) + +var stringOrNumberOrUndefined = C.inStaticMethod; +>stringOrNumberOrUndefined : Symbol(stringOrNumberOrUndefined, Decl(b.ts, 5, 3), Decl(b.ts, 7, 3), Decl(b.ts, 8, 3), Decl(b.ts, 9, 3), Decl(b.ts, 11, 3), Decl(b.ts, 12, 3), Decl(b.ts, 13, 3)) +>C.inStaticMethod : Symbol(C.inStaticMethod, Decl(a.js, 35, 28), Decl(a.js, 38, 14)) +>C : Symbol(C, Decl(a.js, 0, 0)) +>inStaticMethod : Symbol(C.inStaticMethod, Decl(a.js, 35, 28), Decl(a.js, 38, 14)) + +var stringOrNumberOrUndefined = C.inStaticGetter; +>stringOrNumberOrUndefined : Symbol(stringOrNumberOrUndefined, Decl(b.ts, 5, 3), Decl(b.ts, 7, 3), Decl(b.ts, 8, 3), Decl(b.ts, 9, 3), Decl(b.ts, 11, 3), Decl(b.ts, 12, 3), Decl(b.ts, 13, 3)) +>C.inStaticGetter : Symbol(C.inStaticGetter, Decl(a.js, 43, 28), Decl(a.js, 46, 14)) +>C : Symbol(C, Decl(a.js, 0, 0)) +>inStaticGetter : Symbol(C.inStaticGetter, Decl(a.js, 43, 28), Decl(a.js, 46, 14)) + +var stringOrNumberOrUndefined = C.inStaticSetter; +>stringOrNumberOrUndefined : Symbol(stringOrNumberOrUndefined, Decl(b.ts, 5, 3), Decl(b.ts, 7, 3), Decl(b.ts, 8, 3), Decl(b.ts, 9, 3), Decl(b.ts, 11, 3), Decl(b.ts, 12, 3), Decl(b.ts, 13, 3)) +>C.inStaticSetter : Symbol(C.inStaticSetter, Decl(a.js, 51, 28), Decl(a.js, 54, 14)) +>C : Symbol(C, Decl(a.js, 0, 0)) +>inStaticSetter : Symbol(C.inStaticSetter, Decl(a.js, 51, 28), Decl(a.js, 54, 14)) + diff --git a/tests/baselines/reference/inferringClassMembersFromAssignments.types b/tests/baselines/reference/inferringClassMembersFromAssignments.types new file mode 100644 index 00000000000..c1b30ae4519 --- /dev/null +++ b/tests/baselines/reference/inferringClassMembersFromAssignments.types @@ -0,0 +1,234 @@ +=== tests/cases/conformance/salsa/a.js === + +class C { +>C : C + + constructor() { + if (Math.random()) { +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number + + this.inConstructor = 0; +>this.inConstructor = 0 : 0 +>this.inConstructor : string | number +>this : this +>inConstructor : string | number +>0 : 0 + } + else { + this.inConstructor = "string" +>this.inConstructor = "string" : "string" +>this.inConstructor : string | number +>this : this +>inConstructor : string | number +>"string" : "string" + } + } + method() { +>method : () => void + + if (Math.random()) { +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number + + this.inMethod = 0; +>this.inMethod = 0 : 0 +>this.inMethod : string | number | undefined +>this : this +>inMethod : string | number | undefined +>0 : 0 + } + else { + this.inMethod = "string" +>this.inMethod = "string" : "string" +>this.inMethod : string | number | undefined +>this : this +>inMethod : string | number | undefined +>"string" : "string" + } + } + get() { +>get : () => void + + if (Math.random()) { +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number + + this.inGetter = 0; +>this.inGetter = 0 : 0 +>this.inGetter : string | number | undefined +>this : this +>inGetter : string | number | undefined +>0 : 0 + } + else { + this.inGetter = "string" +>this.inGetter = "string" : "string" +>this.inGetter : string | number | undefined +>this : this +>inGetter : string | number | undefined +>"string" : "string" + } + } + set() { +>set : () => void + + if (Math.random()) { +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number + + this.inSetter = 0; +>this.inSetter = 0 : 0 +>this.inSetter : string | number | undefined +>this : this +>inSetter : string | number | undefined +>0 : 0 + } + else { + this.inSetter = "string" +>this.inSetter = "string" : "string" +>this.inSetter : string | number | undefined +>this : this +>inSetter : string | number | undefined +>"string" : "string" + } + } + static method() { +>method : () => void + + if (Math.random()) { +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number + + this.inStaticMethod = 0; +>this.inStaticMethod = 0 : 0 +>this.inStaticMethod : string | number | undefined +>this : typeof C +>inStaticMethod : string | number | undefined +>0 : 0 + } + else { + this.inStaticMethod = "string" +>this.inStaticMethod = "string" : "string" +>this.inStaticMethod : string | number | undefined +>this : typeof C +>inStaticMethod : string | number | undefined +>"string" : "string" + } + } + static get() { +>get : () => void + + if (Math.random()) { +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number + + this.inStaticGetter = 0; +>this.inStaticGetter = 0 : 0 +>this.inStaticGetter : string | number | undefined +>this : typeof C +>inStaticGetter : string | number | undefined +>0 : 0 + } + else { + this.inStaticGetter = "string" +>this.inStaticGetter = "string" : "string" +>this.inStaticGetter : string | number | undefined +>this : typeof C +>inStaticGetter : string | number | undefined +>"string" : "string" + } + } + static set() { +>set : () => void + + if (Math.random()) { +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number + + this.inStaticSetter = 0; +>this.inStaticSetter = 0 : 0 +>this.inStaticSetter : string | number | undefined +>this : typeof C +>inStaticSetter : string | number | undefined +>0 : 0 + } + else { + this.inStaticSetter = "string" +>this.inStaticSetter = "string" : "string" +>this.inStaticSetter : string | number | undefined +>this : typeof C +>inStaticSetter : string | number | undefined +>"string" : "string" + } + } +} + +=== tests/cases/conformance/salsa/b.ts === +var c = new C(); +>c : C +>new C() : C +>C : typeof C + +var stringOrNumber: string | number; +>stringOrNumber : string | number + +var stringOrNumber = c.inConstructor; +>stringOrNumber : string | number +>c.inConstructor : string | number +>c : C +>inConstructor : string | number + +var stringOrNumberOrUndefined: string | number | undefined; +>stringOrNumberOrUndefined : string | number | undefined + +var stringOrNumberOrUndefined = c.inMethod; +>stringOrNumberOrUndefined : string | number | undefined +>c.inMethod : string | number | undefined +>c : C +>inMethod : string | number | undefined + +var stringOrNumberOrUndefined = c.inGetter; +>stringOrNumberOrUndefined : string | number | undefined +>c.inGetter : string | number | undefined +>c : C +>inGetter : string | number | undefined + +var stringOrNumberOrUndefined = c.inSetter; +>stringOrNumberOrUndefined : string | number | undefined +>c.inSetter : string | number | undefined +>c : C +>inSetter : string | number | undefined + +var stringOrNumberOrUndefined = C.inStaticMethod; +>stringOrNumberOrUndefined : string | number | undefined +>C.inStaticMethod : string | number | undefined +>C : typeof C +>inStaticMethod : string | number | undefined + +var stringOrNumberOrUndefined = C.inStaticGetter; +>stringOrNumberOrUndefined : string | number | undefined +>C.inStaticGetter : string | number | undefined +>C : typeof C +>inStaticGetter : string | number | undefined + +var stringOrNumberOrUndefined = C.inStaticSetter; +>stringOrNumberOrUndefined : string | number | undefined +>C.inStaticSetter : string | number | undefined +>C : typeof C +>inStaticSetter : string | number | undefined + diff --git a/tests/cases/conformance/salsa/inferringClassMembersFromAssignments.ts b/tests/cases/conformance/salsa/inferringClassMembersFromAssignments.ts new file mode 100644 index 00000000000..dc63f09b3ab --- /dev/null +++ b/tests/cases/conformance/salsa/inferringClassMembersFromAssignments.ts @@ -0,0 +1,79 @@ +// @out: output.js +// @allowJs: true +// @strictNullChecks: true + +// @filename: a.js +class C { + constructor() { + if (Math.random()) { + this.inConstructor = 0; + } + else { + this.inConstructor = "string" + } + } + method() { + if (Math.random()) { + this.inMethod = 0; + } + else { + this.inMethod = "string" + } + } + get() { + if (Math.random()) { + this.inGetter = 0; + } + else { + this.inGetter = "string" + } + } + set() { + if (Math.random()) { + this.inSetter = 0; + } + else { + this.inSetter = "string" + } + } + static method() { + if (Math.random()) { + this.inStaticMethod = 0; + } + else { + this.inStaticMethod = "string" + } + } + static get() { + if (Math.random()) { + this.inStaticGetter = 0; + } + else { + this.inStaticGetter = "string" + } + } + static set() { + if (Math.random()) { + this.inStaticSetter = 0; + } + else { + this.inStaticSetter = "string" + } + } +} + +// @filename: b.ts +var c = new C(); + +var stringOrNumber: string | number; +var stringOrNumber = c.inConstructor; + +var stringOrNumberOrUndefined: string | number | undefined; + +var stringOrNumberOrUndefined = c.inMethod; +var stringOrNumberOrUndefined = c.inGetter; +var stringOrNumberOrUndefined = c.inSetter; + +var stringOrNumberOrUndefined = C.inStaticMethod; +var stringOrNumberOrUndefined = C.inStaticGetter; +var stringOrNumberOrUndefined = C.inStaticSetter; From 9dc2bae2e657dd4c4553b9c0f3e7bb91f9dc10bf Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 24 Feb 2017 18:00:27 -0800 Subject: [PATCH 16/65] Use contextual type of object literal as 'this' in methods --- src/compiler/checker.ts | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8c1a91d203d..0218f21a27f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11512,25 +11512,26 @@ namespace ts { const containingLiteral = getContainingObjectLiteral(func); if (containingLiteral) { // We have an object literal method. Check if the containing object literal has a contextual type - // and if that contextual type is or includes a ThisType. If so, T is the contextual type for - // 'this'. We continue looking in any directly enclosing object literals. - let objectLiteral = containingLiteral; - while (true) { - const type = getApparentTypeOfContextualType(objectLiteral); - if (type) { - const thisType = getThisTypeFromContextualType(type); - if (thisType) { - return thisType; - } + // that includes a ThisType. If so, T is the contextual type for 'this'. We continue looking in + // any directly enclosing object literals. + const contextualType = getApparentTypeOfContextualType(containingLiteral); + let literal = containingLiteral; + let type = contextualType; + while (type) { + const thisType = getThisTypeFromContextualType(type); + if (thisType) { + return thisType; } - if (objectLiteral.parent.kind !== SyntaxKind.PropertyAssignment) { + if (literal.parent.kind !== SyntaxKind.PropertyAssignment) { break; } - objectLiteral = objectLiteral.parent.parent; + literal = literal.parent.parent; + type = getApparentTypeOfContextualType(literal); } // There was no contextual ThisType for the containing object literal, so the contextual type - // for 'this' is the type of the object literal itself. - return checkExpressionCached(containingLiteral); + // for 'this' is the contextual type for the containing object literal or the type of the object + // literal itself. + return contextualType || checkExpressionCached(containingLiteral); } // In an assignment of the form 'obj.xxx = function(...)' or 'obj[xxx] = function(...)', the // contextual type for 'this' is 'obj'. From 16f403058fccec462c83ec7b7f9640e5f233ffd2 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 24 Feb 2017 18:12:09 -0800 Subject: [PATCH 17/65] Accept new baselines --- tests/baselines/reference/castTest.symbols | 12 +-- tests/baselines/reference/castTest.types | 4 +- .../commentsOnObjectLiteral2.errors.txt | 5 +- .../reference/fixSignatureCaching.errors.txt | 98 +------------------ .../baselines/reference/objectSpread.symbols | 6 +- tests/baselines/reference/objectSpread.types | 2 +- .../reference/thisTypeInFunctions2.symbols | 18 ++-- .../reference/thisTypeInFunctions2.types | 18 ++-- 8 files changed, 30 insertions(+), 133 deletions(-) diff --git a/tests/baselines/reference/castTest.symbols b/tests/baselines/reference/castTest.symbols index 706f75a1028..0baee00ec47 100644 --- a/tests/baselines/reference/castTest.symbols +++ b/tests/baselines/reference/castTest.symbols @@ -71,13 +71,13 @@ var p_cast = ({ return new Point(this.x + dx, this.y + dy); >Point : Symbol(Point, Decl(castTest.ts, 11, 37)) ->this.x : Symbol(x, Decl(castTest.ts, 22, 23)) ->this : Symbol(__object, Decl(castTest.ts, 22, 22)) ->x : Symbol(x, Decl(castTest.ts, 22, 23)) +>this.x : Symbol(Point.x, Decl(castTest.ts, 14, 1)) +>this : Symbol(Point, Decl(castTest.ts, 11, 37)) +>x : Symbol(Point.x, Decl(castTest.ts, 14, 1)) >dx : Symbol(dx, Decl(castTest.ts, 25, 18)) ->this.y : Symbol(y, Decl(castTest.ts, 23, 9)) ->this : Symbol(__object, Decl(castTest.ts, 22, 22)) ->y : Symbol(y, Decl(castTest.ts, 23, 9)) +>this.y : Symbol(Point.y, Decl(castTest.ts, 15, 14)) +>this : Symbol(Point, Decl(castTest.ts, 11, 37)) +>y : Symbol(Point.y, Decl(castTest.ts, 15, 14)) >dy : Symbol(dy, Decl(castTest.ts, 25, 21)) }, diff --git a/tests/baselines/reference/castTest.types b/tests/baselines/reference/castTest.types index acdc58d0b25..08c9853dca6 100644 --- a/tests/baselines/reference/castTest.types +++ b/tests/baselines/reference/castTest.types @@ -93,12 +93,12 @@ var p_cast = ({ >Point : typeof Point >this.x + dx : number >this.x : number ->this : { x: number; y: number; add: (dx: number, dy: number) => Point; mult: (p: Point) => Point; } +>this : Point >x : number >dx : number >this.y + dy : number >this.y : number ->this : { x: number; y: number; add: (dx: number, dy: number) => Point; mult: (p: Point) => Point; } +>this : Point >y : number >dy : number diff --git a/tests/baselines/reference/commentsOnObjectLiteral2.errors.txt b/tests/baselines/reference/commentsOnObjectLiteral2.errors.txt index 3748d0387b6..2a2394ced48 100644 --- a/tests/baselines/reference/commentsOnObjectLiteral2.errors.txt +++ b/tests/baselines/reference/commentsOnObjectLiteral2.errors.txt @@ -1,8 +1,7 @@ tests/cases/compiler/commentsOnObjectLiteral2.ts(1,14): error TS2304: Cannot find name 'makeClass'. -tests/cases/compiler/commentsOnObjectLiteral2.ts(9,17): error TS2339: Property 'name' does not exist on type '{ initialize: (name: any) => void; }'. -==== tests/cases/compiler/commentsOnObjectLiteral2.ts (2 errors) ==== +==== tests/cases/compiler/commentsOnObjectLiteral2.ts (1 errors) ==== var Person = makeClass( ~~~~~~~~~ !!! error TS2304: Cannot find name 'makeClass'. @@ -14,8 +13,6 @@ tests/cases/compiler/commentsOnObjectLiteral2.ts(9,17): error TS2339: Property ' */ initialize: function(name) { this.name = name; - ~~~~ -!!! error TS2339: Property 'name' does not exist on type '{ initialize: (name: any) => void; }'. } /* trailing comment 1*/, } ); \ No newline at end of file diff --git a/tests/baselines/reference/fixSignatureCaching.errors.txt b/tests/baselines/reference/fixSignatureCaching.errors.txt index 284a0d13926..7a5c43c966e 100644 --- a/tests/baselines/reference/fixSignatureCaching.errors.txt +++ b/tests/baselines/reference/fixSignatureCaching.errors.txt @@ -41,51 +41,19 @@ tests/cases/conformance/fixSignatureCaching.ts(639,38): error TS2304: Cannot fin tests/cases/conformance/fixSignatureCaching.ts(640,13): error TS2304: Cannot find name 'window'. tests/cases/conformance/fixSignatureCaching.ts(641,13): error TS2304: Cannot find name 'window'. tests/cases/conformance/fixSignatureCaching.ts(704,18): error TS2339: Property 'prepareDetectionCache' does not exist on type '{}'. -tests/cases/conformance/fixSignatureCaching.ts(704,45): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. -tests/cases/conformance/fixSignatureCaching.ts(704,58): error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. -tests/cases/conformance/fixSignatureCaching.ts(704,67): error TS2339: Property 'maxPhoneWidth' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. -tests/cases/conformance/fixSignatureCaching.ts(705,25): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. tests/cases/conformance/fixSignatureCaching.ts(734,18): error TS2339: Property 'prepareDetectionCache' does not exist on type '{}'. -tests/cases/conformance/fixSignatureCaching.ts(734,45): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. -tests/cases/conformance/fixSignatureCaching.ts(734,58): error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. -tests/cases/conformance/fixSignatureCaching.ts(734,67): error TS2339: Property 'maxPhoneWidth' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. -tests/cases/conformance/fixSignatureCaching.ts(735,25): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. tests/cases/conformance/fixSignatureCaching.ts(783,18): error TS2339: Property 'prepareDetectionCache' does not exist on type '{}'. -tests/cases/conformance/fixSignatureCaching.ts(783,45): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. -tests/cases/conformance/fixSignatureCaching.ts(783,58): error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. -tests/cases/conformance/fixSignatureCaching.ts(783,67): error TS2339: Property 'maxPhoneWidth' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. -tests/cases/conformance/fixSignatureCaching.ts(784,25): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. -tests/cases/conformance/fixSignatureCaching.ts(804,22): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. -tests/cases/conformance/fixSignatureCaching.ts(805,22): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. tests/cases/conformance/fixSignatureCaching.ts(805,46): error TS2339: Property 'findMatch' does not exist on type '{}'. tests/cases/conformance/fixSignatureCaching.ts(805,61): error TS2339: Property 'mobileDetectRules' does not exist on type '{}'. -tests/cases/conformance/fixSignatureCaching.ts(805,89): error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. -tests/cases/conformance/fixSignatureCaching.ts(807,25): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. -tests/cases/conformance/fixSignatureCaching.ts(827,22): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. -tests/cases/conformance/fixSignatureCaching.ts(828,22): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. tests/cases/conformance/fixSignatureCaching.ts(828,47): error TS2339: Property 'findMatches' does not exist on type '{}'. tests/cases/conformance/fixSignatureCaching.ts(828,64): error TS2339: Property 'mobileDetectRules' does not exist on type '{}'. -tests/cases/conformance/fixSignatureCaching.ts(828,92): error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. -tests/cases/conformance/fixSignatureCaching.ts(830,25): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. -tests/cases/conformance/fixSignatureCaching.ts(844,22): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. -tests/cases/conformance/fixSignatureCaching.ts(845,22): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. tests/cases/conformance/fixSignatureCaching.ts(845,39): error TS2339: Property 'detectOS' does not exist on type '{}'. -tests/cases/conformance/fixSignatureCaching.ts(845,53): error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. -tests/cases/conformance/fixSignatureCaching.ts(847,25): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. tests/cases/conformance/fixSignatureCaching.ts(869,25): error TS2339: Property 'getVersion' does not exist on type '{}'. -tests/cases/conformance/fixSignatureCaching.ts(869,46): error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. tests/cases/conformance/fixSignatureCaching.ts(890,25): error TS2339: Property 'getVersionStr' does not exist on type '{}'. -tests/cases/conformance/fixSignatureCaching.ts(890,49): error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. tests/cases/conformance/fixSignatureCaching.ts(912,36): error TS2339: Property 'findMatches' does not exist on type '{}'. tests/cases/conformance/fixSignatureCaching.ts(912,53): error TS2339: Property 'mobileDetectRules' does not exist on type '{}'. -tests/cases/conformance/fixSignatureCaching.ts(912,83): error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. -tests/cases/conformance/fixSignatureCaching.ts(927,38): error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. tests/cases/conformance/fixSignatureCaching.ts(941,33): error TS2339: Property 'isPhoneSized' does not exist on type '(userAgent: any, maxPhoneWidth: any) => void'. -tests/cases/conformance/fixSignatureCaching.ts(941,68): error TS2339: Property 'maxPhoneWidth' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. -tests/cases/conformance/fixSignatureCaching.ts(951,22): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. -tests/cases/conformance/fixSignatureCaching.ts(952,22): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. tests/cases/conformance/fixSignatureCaching.ts(952,42): error TS2339: Property 'mobileGrade' does not exist on type '{}'. -tests/cases/conformance/fixSignatureCaching.ts(954,25): error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. tests/cases/conformance/fixSignatureCaching.ts(959,16): error TS2304: Cannot find name 'window'. tests/cases/conformance/fixSignatureCaching.ts(959,42): error TS2304: Cannot find name 'window'. tests/cases/conformance/fixSignatureCaching.ts(960,22): error TS2339: Property 'isPhoneSized' does not exist on type '(userAgent: any, maxPhoneWidth: any) => void'. @@ -103,7 +71,7 @@ tests/cases/conformance/fixSignatureCaching.ts(979,23): error TS2304: Cannot fin tests/cases/conformance/fixSignatureCaching.ts(980,37): error TS2304: Cannot find name 'window'. -==== tests/cases/conformance/fixSignatureCaching.ts (103 errors) ==== +==== tests/cases/conformance/fixSignatureCaching.ts (71 errors) ==== // Repro from #10697 (function (define, undefined) { @@ -894,15 +862,7 @@ tests/cases/conformance/fixSignatureCaching.ts(980,37): error TS2304: Cannot fin impl.prepareDetectionCache(this._cache, this.ua, this.maxPhoneWidth); ~~~~~~~~~~~~~~~~~~~~~ !!! error TS2339: Property 'prepareDetectionCache' does not exist on type '{}'. - ~~~~~~ -!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. - ~~ -!!! error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. - ~~~~~~~~~~~~~ -!!! error TS2339: Property 'maxPhoneWidth' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. return this._cache.mobile; - ~~~~~~ -!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. }, /** @@ -934,15 +894,7 @@ tests/cases/conformance/fixSignatureCaching.ts(980,37): error TS2304: Cannot fin impl.prepareDetectionCache(this._cache, this.ua, this.maxPhoneWidth); ~~~~~~~~~~~~~~~~~~~~~ !!! error TS2339: Property 'prepareDetectionCache' does not exist on type '{}'. - ~~~~~~ -!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. - ~~ -!!! error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. - ~~~~~~~~~~~~~ -!!! error TS2339: Property 'maxPhoneWidth' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. return this._cache.phone; - ~~~~~~ -!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. }, /** @@ -993,15 +945,7 @@ tests/cases/conformance/fixSignatureCaching.ts(980,37): error TS2304: Cannot fin impl.prepareDetectionCache(this._cache, this.ua, this.maxPhoneWidth); ~~~~~~~~~~~~~~~~~~~~~ !!! error TS2339: Property 'prepareDetectionCache' does not exist on type '{}'. - ~~~~~~ -!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. - ~~ -!!! error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. - ~~~~~~~~~~~~~ -!!! error TS2339: Property 'maxPhoneWidth' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. return this._cache.tablet; - ~~~~~~ -!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. }, /** @@ -1022,21 +966,13 @@ tests/cases/conformance/fixSignatureCaching.ts(980,37): error TS2304: Cannot fin */ userAgent: function () { if (this._cache.userAgent === undefined) { - ~~~~~~ -!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. this._cache.userAgent = impl.findMatch(impl.mobileDetectRules.uas, this.ua); - ~~~~~~ -!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. ~~~~~~~~~ !!! error TS2339: Property 'findMatch' does not exist on type '{}'. ~~~~~~~~~~~~~~~~~ !!! error TS2339: Property 'mobileDetectRules' does not exist on type '{}'. - ~~ -!!! error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. } return this._cache.userAgent; - ~~~~~~ -!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. }, /** @@ -1057,21 +993,13 @@ tests/cases/conformance/fixSignatureCaching.ts(980,37): error TS2304: Cannot fin */ userAgents: function () { if (this._cache.userAgents === undefined) { - ~~~~~~ -!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. this._cache.userAgents = impl.findMatches(impl.mobileDetectRules.uas, this.ua); - ~~~~~~ -!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. ~~~~~~~~~~~ !!! error TS2339: Property 'findMatches' does not exist on type '{}'. ~~~~~~~~~~~~~~~~~ !!! error TS2339: Property 'mobileDetectRules' does not exist on type '{}'. - ~~ -!!! error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. } return this._cache.userAgents; - ~~~~~~ -!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. }, /** @@ -1086,19 +1014,11 @@ tests/cases/conformance/fixSignatureCaching.ts(980,37): error TS2304: Cannot fin */ os: function () { if (this._cache.os === undefined) { - ~~~~~~ -!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. this._cache.os = impl.detectOS(this.ua); - ~~~~~~ -!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. ~~~~~~~~ !!! error TS2339: Property 'detectOS' does not exist on type '{}'. - ~~ -!!! error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. } return this._cache.os; - ~~~~~~ -!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. }, /** @@ -1123,8 +1043,6 @@ tests/cases/conformance/fixSignatureCaching.ts(980,37): error TS2304: Cannot fin return impl.getVersion(key, this.ua); ~~~~~~~~~~ !!! error TS2339: Property 'getVersion' does not exist on type '{}'. - ~~ -!!! error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. }, /** @@ -1148,8 +1066,6 @@ tests/cases/conformance/fixSignatureCaching.ts(980,37): error TS2304: Cannot fin return impl.getVersionStr(key, this.ua); ~~~~~~~~~~~~~ !!! error TS2339: Property 'getVersionStr' does not exist on type '{}'. - ~~ -!!! error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. }, /** @@ -1176,8 +1092,6 @@ tests/cases/conformance/fixSignatureCaching.ts(980,37): error TS2304: Cannot fin !!! error TS2339: Property 'findMatches' does not exist on type '{}'. ~~~~~~~~~~~~~~~~~ !!! error TS2339: Property 'mobileDetectRules' does not exist on type '{}'. - ~~ -!!! error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. }, /** @@ -1193,8 +1107,6 @@ tests/cases/conformance/fixSignatureCaching.ts(980,37): error TS2304: Cannot fin pattern = new RegExp(pattern, 'i'); } return pattern.test(this.ua); - ~~ -!!! error TS2339: Property 'ua' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. }, /** @@ -1211,8 +1123,6 @@ tests/cases/conformance/fixSignatureCaching.ts(980,37): error TS2304: Cannot fin return MobileDetect.isPhoneSized(maxPhoneWidth || this.maxPhoneWidth); ~~~~~~~~~~~~ !!! error TS2339: Property 'isPhoneSized' does not exist on type '(userAgent: any, maxPhoneWidth: any) => void'. - ~~~~~~~~~~~~~ -!!! error TS2339: Property 'maxPhoneWidth' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. }, /** @@ -1223,17 +1133,11 @@ tests/cases/conformance/fixSignatureCaching.ts(980,37): error TS2304: Cannot fin */ mobileGrade: function () { if (this._cache.grade === undefined) { - ~~~~~~ -!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. this._cache.grade = impl.mobileGrade(this); - ~~~~~~ -!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. ~~~~~~~~~~~ !!! error TS2339: Property 'mobileGrade' does not exist on type '{}'. } return this._cache.grade; - ~~~~~~ -!!! error TS2339: Property '_cache' does not exist on type '{ constructor: (userAgent: any, maxPhoneWidth: any) => void; mobile: () => any; phone: () => any; tablet: () => any; userAgent: () => any; userAgents: () => any; os: () => any; version: (key: any) => any; versionStr: (key: any) => any; is: (key: any) => any; match: (pattern: any) => any; isPhoneSized: (maxPhoneWidth: any) => any; mobileGrade: () => any; }'. } }; diff --git a/tests/baselines/reference/objectSpread.symbols b/tests/baselines/reference/objectSpread.symbols index a734066d5e7..0538121e90c 100644 --- a/tests/baselines/reference/objectSpread.symbols +++ b/tests/baselines/reference/objectSpread.symbols @@ -200,9 +200,9 @@ let cplus: { p: number, plus(): void } = { ...c, plus() { return this.p + 1; } } >plus : Symbol(plus, Decl(objectSpread.ts, 49, 23)) >c : Symbol(c, Decl(objectSpread.ts, 45, 3)) >plus : Symbol(plus, Decl(objectSpread.ts, 49, 48)) ->this.p : Symbol(C.p, Decl(objectSpread.ts, 44, 9)) ->this : Symbol(cplus, Decl(objectSpread.ts, 49, 40)) ->p : Symbol(C.p, Decl(objectSpread.ts, 44, 9)) +>this.p : Symbol(p, Decl(objectSpread.ts, 49, 12)) +>this : Symbol(cplus, Decl(objectSpread.ts, 49, 10)) +>p : Symbol(p, Decl(objectSpread.ts, 49, 12)) cplus.plus(); >cplus.plus : Symbol(plus, Decl(objectSpread.ts, 49, 23)) diff --git a/tests/baselines/reference/objectSpread.types b/tests/baselines/reference/objectSpread.types index b6ad1d13ae4..3a736721425 100644 --- a/tests/baselines/reference/objectSpread.types +++ b/tests/baselines/reference/objectSpread.types @@ -268,7 +268,7 @@ let cplus: { p: number, plus(): void } = { ...c, plus() { return this.p + 1; } } >plus : () => number >this.p + 1 : number >this.p : number ->this : { plus(): number; p: number; } +>this : { p: number; plus(): void; } >p : number >1 : 1 diff --git a/tests/baselines/reference/thisTypeInFunctions2.symbols b/tests/baselines/reference/thisTypeInFunctions2.symbols index d9d0be723b6..6811ef4a234 100644 --- a/tests/baselines/reference/thisTypeInFunctions2.symbols +++ b/tests/baselines/reference/thisTypeInFunctions2.symbols @@ -90,12 +90,10 @@ extend2({ >init : Symbol(init, Decl(thisTypeInFunctions2.ts, 32, 9)) this // this: containing object literal type ->this : Symbol(__object, Decl(thisTypeInFunctions2.ts, 32, 8)) +>this : Symbol(IndexedWithoutThis, Decl(thisTypeInFunctions2.ts, 5, 1)) this.mine ->this.mine : Symbol(mine, Decl(thisTypeInFunctions2.ts, 37, 6)) ->this : Symbol(__object, Decl(thisTypeInFunctions2.ts, 32, 8)) ->mine : Symbol(mine, Decl(thisTypeInFunctions2.ts, 37, 6)) +>this : Symbol(IndexedWithoutThis, Decl(thisTypeInFunctions2.ts, 5, 1)) //this.willDestroy }, @@ -106,12 +104,10 @@ extend2({ >foo : Symbol(foo, Decl(thisTypeInFunctions2.ts, 38, 13)) this // this: containing object literal type ->this : Symbol(__object, Decl(thisTypeInFunctions2.ts, 32, 8)) +>this : Symbol(IndexedWithoutThis, Decl(thisTypeInFunctions2.ts, 5, 1)) this.mine ->this.mine : Symbol(mine, Decl(thisTypeInFunctions2.ts, 37, 6)) ->this : Symbol(__object, Decl(thisTypeInFunctions2.ts, 32, 8)) ->mine : Symbol(mine, Decl(thisTypeInFunctions2.ts, 37, 6)) +>this : Symbol(IndexedWithoutThis, Decl(thisTypeInFunctions2.ts, 5, 1)) } }); @@ -126,9 +122,9 @@ simple({ >n.length : Symbol(String.length, Decl(lib.d.ts, --, --)) >n : Symbol(n, Decl(thisTypeInFunctions2.ts, 46, 8)) >length : Symbol(String.length, Decl(lib.d.ts, --, --)) ->this.bar : Symbol(bar, Decl(thisTypeInFunctions2.ts, 48, 6)) ->this : Symbol(__object, Decl(thisTypeInFunctions2.ts, 45, 7)) ->bar : Symbol(bar, Decl(thisTypeInFunctions2.ts, 48, 6)) +>this.bar : Symbol(SimpleInterface.bar, Decl(thisTypeInFunctions2.ts, 13, 19)) +>this : Symbol(SimpleInterface, Decl(thisTypeInFunctions2.ts, 11, 1)) +>bar : Symbol(SimpleInterface.bar, Decl(thisTypeInFunctions2.ts, 13, 19)) }, bar() { diff --git a/tests/baselines/reference/thisTypeInFunctions2.types b/tests/baselines/reference/thisTypeInFunctions2.types index f79426529ea..79169a715d5 100644 --- a/tests/baselines/reference/thisTypeInFunctions2.types +++ b/tests/baselines/reference/thisTypeInFunctions2.types @@ -100,12 +100,12 @@ extend2({ >init : () => void this // this: containing object literal type ->this : { init(): void; mine: number; foo(): void; } +>this : IndexedWithoutThis this.mine ->this.mine : number ->this : { init(): void; mine: number; foo(): void; } ->mine : number +>this.mine : any +>this : IndexedWithoutThis +>mine : any //this.willDestroy }, @@ -117,12 +117,12 @@ extend2({ >foo : () => void this // this: containing object literal type ->this : { init(): void; mine: number; foo(): void; } +>this : IndexedWithoutThis this.mine ->this.mine : number ->this : { init(): void; mine: number; foo(): void; } ->mine : number +>this.mine : any +>this : IndexedWithoutThis +>mine : any } }); @@ -142,7 +142,7 @@ simple({ >length : number >this.bar() : number >this.bar : () => number ->this : { foo(n: string): number; bar(): number; } +>this : SimpleInterface >bar : () => number }, From 20b4523d0ffa92454ddb3ed683c8c89a14e46ef5 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 24 Feb 2017 19:52:22 -0800 Subject: [PATCH 18/65] Rename applyToContextualType to mapType and remove old mapType --- src/compiler/checker.ts | 60 +++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0218f21a27f..f451871d2bb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10041,8 +10041,31 @@ namespace ts { return f(type) ? type : neverType; } - function mapType(type: Type, f: (t: Type) => Type): Type { - return type.flags & TypeFlags.Union ? getUnionType(map((type).types, f)) : f(type); + // Apply a mapping function to a contextual type and return the resulting type. If the contextual type + // is a union type, the mapping function is applied to each constituent type and a union of the resulting + // types is returned. + function mapType(type: Type, mapper: (t: Type) => Type): Type { + if (!(type.flags & TypeFlags.Union)) { + return mapper(type); + } + const types = (type).types; + let mappedType: Type; + let mappedTypes: Type[]; + for (const current of types) { + const t = mapper(current); + if (t) { + if (!mappedType) { + mappedType = t; + } + else if (!mappedTypes) { + mappedTypes = [mappedType, t]; + } + else { + mappedTypes.push(t); + } + } + } + return mappedTypes ? getUnionType(mappedTypes) : mappedType; } function extractTypesOfKind(type: Type, kind: TypeFlags) { @@ -11491,7 +11514,7 @@ namespace ts { } function getThisTypeFromContextualType(type: Type): Type { - return applyToContextualType(type, t => { + return mapType(type, t => { return t.flags & TypeFlags.Intersection ? forEach((t).types, getThisTypeArgument) : getThisTypeArgument(t); }); } @@ -11739,42 +11762,15 @@ namespace ts { return undefined; } - // Apply a mapping function to a contextual type and return the resulting type. If the contextual type - // is a union type, the mapping function is applied to each constituent type and a union of the resulting - // types is returned. - function applyToContextualType(type: Type, mapper: (t: Type) => Type): Type { - if (!(type.flags & TypeFlags.Union)) { - return mapper(type); - } - const types = (type).types; - let mappedType: Type; - let mappedTypes: Type[]; - for (const current of types) { - const t = mapper(current); - if (t) { - if (!mappedType) { - mappedType = t; - } - else if (!mappedTypes) { - mappedTypes = [mappedType, t]; - } - else { - mappedTypes.push(t); - } - } - } - return mappedTypes ? getUnionType(mappedTypes) : mappedType; - } - function getTypeOfPropertyOfContextualType(type: Type, name: string) { - return applyToContextualType(type, t => { + return mapType(type, t => { const prop = t.flags & TypeFlags.StructuredType ? getPropertyOfType(t, name) : undefined; return prop ? getTypeOfSymbol(prop) : undefined; }); } function getIndexTypeOfContextualType(type: Type, kind: IndexKind) { - return applyToContextualType(type, t => getIndexTypeOfStructuredType(t, kind)); + return mapType(type, t => getIndexTypeOfStructuredType(t, kind)); } // Return true if the given contextual type is a tuple-like type From 6fdd929a66ef6cb9eb7ec5b092b079ac1eb4b0ff Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 24 Feb 2017 19:52:50 -0800 Subject: [PATCH 19/65] Update test --- tests/baselines/reference/thisTypeInFunctions2.js | 2 -- .../reference/thisTypeInFunctions2.symbols | 13 ++++++------- .../baselines/reference/thisTypeInFunctions2.types | 5 ++--- .../types/thisType/thisTypeInFunctions2.ts | 1 - 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/tests/baselines/reference/thisTypeInFunctions2.js b/tests/baselines/reference/thisTypeInFunctions2.js index 45b26fe84d8..978f79483b0 100644 --- a/tests/baselines/reference/thisTypeInFunctions2.js +++ b/tests/baselines/reference/thisTypeInFunctions2.js @@ -35,7 +35,6 @@ extend2({ init() { this // this: containing object literal type this.mine - //this.willDestroy }, mine: 13, foo() { @@ -71,7 +70,6 @@ extend2({ init: function () { this; // this: containing object literal type this.mine; - //this.willDestroy }, mine: 13, foo: function () { diff --git a/tests/baselines/reference/thisTypeInFunctions2.symbols b/tests/baselines/reference/thisTypeInFunctions2.symbols index 6811ef4a234..d4b19caddb4 100644 --- a/tests/baselines/reference/thisTypeInFunctions2.symbols +++ b/tests/baselines/reference/thisTypeInFunctions2.symbols @@ -95,13 +95,12 @@ extend2({ this.mine >this : Symbol(IndexedWithoutThis, Decl(thisTypeInFunctions2.ts, 5, 1)) - //this.willDestroy }, mine: 13, ->mine : Symbol(mine, Decl(thisTypeInFunctions2.ts, 37, 6)) +>mine : Symbol(mine, Decl(thisTypeInFunctions2.ts, 36, 6)) foo() { ->foo : Symbol(foo, Decl(thisTypeInFunctions2.ts, 38, 13)) +>foo : Symbol(foo, Decl(thisTypeInFunctions2.ts, 37, 13)) this // this: containing object literal type >this : Symbol(IndexedWithoutThis, Decl(thisTypeInFunctions2.ts, 5, 1)) @@ -115,12 +114,12 @@ simple({ >simple : Symbol(simple, Decl(thisTypeInFunctions2.ts, 17, 57)) foo(n) { ->foo : Symbol(foo, Decl(thisTypeInFunctions2.ts, 45, 8)) ->n : Symbol(n, Decl(thisTypeInFunctions2.ts, 46, 8)) +>foo : Symbol(foo, Decl(thisTypeInFunctions2.ts, 44, 8)) +>n : Symbol(n, Decl(thisTypeInFunctions2.ts, 45, 8)) return n.length + this.bar(); >n.length : Symbol(String.length, Decl(lib.d.ts, --, --)) ->n : Symbol(n, Decl(thisTypeInFunctions2.ts, 46, 8)) +>n : Symbol(n, Decl(thisTypeInFunctions2.ts, 45, 8)) >length : Symbol(String.length, Decl(lib.d.ts, --, --)) >this.bar : Symbol(SimpleInterface.bar, Decl(thisTypeInFunctions2.ts, 13, 19)) >this : Symbol(SimpleInterface, Decl(thisTypeInFunctions2.ts, 11, 1)) @@ -128,7 +127,7 @@ simple({ }, bar() { ->bar : Symbol(bar, Decl(thisTypeInFunctions2.ts, 48, 6)) +>bar : Symbol(bar, Decl(thisTypeInFunctions2.ts, 47, 6)) return 14; } diff --git a/tests/baselines/reference/thisTypeInFunctions2.types b/tests/baselines/reference/thisTypeInFunctions2.types index 79169a715d5..a527429ccd9 100644 --- a/tests/baselines/reference/thisTypeInFunctions2.types +++ b/tests/baselines/reference/thisTypeInFunctions2.types @@ -92,9 +92,9 @@ extend1({ } }); extend2({ ->extend2({ init() { this // this: containing object literal type this.mine //this.willDestroy }, mine: 13, foo() { this // this: containing object literal type this.mine }}) : void +>extend2({ init() { this // this: containing object literal type this.mine }, mine: 13, foo() { this // this: containing object literal type this.mine }}) : void >extend2 : (args: IndexedWithoutThis) => void ->{ init() { this // this: containing object literal type this.mine //this.willDestroy }, mine: 13, foo() { this // this: containing object literal type this.mine }} : { init(): void; mine: number; foo(): void; } +>{ init() { this // this: containing object literal type this.mine }, mine: 13, foo() { this // this: containing object literal type this.mine }} : { init(): void; mine: number; foo(): void; } init() { >init : () => void @@ -107,7 +107,6 @@ extend2({ >this : IndexedWithoutThis >mine : any - //this.willDestroy }, mine: 13, >mine : number diff --git a/tests/cases/conformance/types/thisType/thisTypeInFunctions2.ts b/tests/cases/conformance/types/thisType/thisTypeInFunctions2.ts index 0d1581633c3..1c80e21aa16 100644 --- a/tests/cases/conformance/types/thisType/thisTypeInFunctions2.ts +++ b/tests/cases/conformance/types/thisType/thisTypeInFunctions2.ts @@ -34,7 +34,6 @@ extend2({ init() { this // this: containing object literal type this.mine - //this.willDestroy }, mine: 13, foo() { From cd87d903a022a5aa2e94f57cb7fb9abc646aa61e Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 27 Feb 2017 10:19:14 -0800 Subject: [PATCH 20/65] Update comment --- 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 f451871d2bb..ff3a1079b18 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10041,9 +10041,9 @@ namespace ts { return f(type) ? type : neverType; } - // Apply a mapping function to a contextual type and return the resulting type. If the contextual type - // is a union type, the mapping function is applied to each constituent type and a union of the resulting - // types is returned. + // Apply a mapping function to a type and return the resulting type. If the source type + // is a union type, the mapping function is applied to each constituent type and a union + // of the resulting types is returned. function mapType(type: Type, mapper: (t: Type) => Type): Type { if (!(type.flags & TypeFlags.Union)) { return mapper(type); From 5bda48ba8d44717cb7038c70d365438de69ce09b Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 27 Feb 2017 10:19:26 -0800 Subject: [PATCH 21/65] Add tests --- .../reference/thisTypeInObjectLiterals2.js | 293 +++++++++++ .../thisTypeInObjectLiterals2.symbols | 410 ++++++++++++++++ .../reference/thisTypeInObjectLiterals2.types | 463 ++++++++++++++++++ .../thisType/thisTypeInObjectLiterals2.ts | 144 ++++++ 4 files changed, 1310 insertions(+) create mode 100644 tests/baselines/reference/thisTypeInObjectLiterals2.js create mode 100644 tests/baselines/reference/thisTypeInObjectLiterals2.symbols create mode 100644 tests/baselines/reference/thisTypeInObjectLiterals2.types create mode 100644 tests/cases/conformance/types/thisType/thisTypeInObjectLiterals2.ts diff --git a/tests/baselines/reference/thisTypeInObjectLiterals2.js b/tests/baselines/reference/thisTypeInObjectLiterals2.js new file mode 100644 index 00000000000..08f02b6c5af --- /dev/null +++ b/tests/baselines/reference/thisTypeInObjectLiterals2.js @@ -0,0 +1,293 @@ +//// [thisTypeInObjectLiterals2.ts] + +// In methods of an object literal with no contextual type, 'this' has the type +// of the object literal. + +let obj1 = { + a: 1, + f() { + return this.a; + }, + b: "hello", + c: { + g() { + this.g(); + } + }, + get d() { + return this.a; + }, + get e() { + return this.b; + }, + set e(value) { + this.b = value; + } +}; + +// In methods of an object literal with a contextual type, 'this' has the +// contextual type. + +type Point = { + x: number; + y: number; + moveBy(dx: number, dy: number): void; +} + +let p1: Point = { + x: 10, + y: 20, + moveBy(dx, dy) { + this.x += dx; + this.y += dy; + } +}; + +declare function f1(p: Point): void; + +f1({ + x: 10, + y: 20, + moveBy(dx, dy) { + this.x += dx; + this.y += dy; + } +}); + +// In methods of an object literal with a contextual type that includes some +// ThisType, 'this' is of type T. + +type ObjectDescriptor = { + data?: D; + methods?: M & ThisType; // Type of 'this' in methods is D & M +} + +declare function makeObject(desc: ObjectDescriptor): D & M; + +let x1 = makeObject({ + data: { x: 0, y: 0 }, + methods: { + moveBy(dx: number, dy: number) { + this.x += dx; // Strongly typed this + this.y += dy; // Strongly typed this + } + } +}); + +// In methods contained in an object literal with a contextual type that includes +// some ThisType, 'this' is of type T. + +type ObjectDescriptor2 = ThisType & { + data?: D; + methods?: M; +} + +declare function makeObject2(desc: ObjectDescriptor): D & M; + +let x2 = makeObject2({ + data: { x: 0, y: 0 }, + methods: { + moveBy(dx: number, dy: number) { + this.x += dx; // Strongly typed this + this.y += dy; // Strongly typed this + } + } +}); + +// Proof of concept for typing of Vue.js + +type Accessors = { [K in keyof T]: (() => T[K]) | Computed }; + +type Dictionary = { [x: string]: T } + +type Computed = { + get?(): T; + set?(value: T): void; +} + +type VueOptions = ThisType & { + data?: D | (() => D); + methods?: M; + computed?: Accessors

; +} + +declare const Vue: new (options: VueOptions) => D & M & P; + +let vue = new Vue({ + data: () => ({ x: 1, y: 2 }), + methods: { + f(x: string) { + return this.x; + } + }, + computed: { + test(): number { + return this.x; + }, + hello: { + get() { + return "hi"; + }, + set(value: string) { + } + } + } +}); + +vue; +vue.x; +vue.f("abc"); +vue.test; +vue.hello; + + +//// [thisTypeInObjectLiterals2.js] +// In methods of an object literal with no contextual type, 'this' has the type +// of the object literal. +var obj1 = { + a: 1, + f: function () { + return this.a; + }, + b: "hello", + c: { + g: function () { + this.g(); + } + }, + get d() { + return this.a; + }, + get e() { + return this.b; + }, + set e(value) { + this.b = value; + } +}; +var p1 = { + x: 10, + y: 20, + moveBy: function (dx, dy) { + this.x += dx; + this.y += dy; + } +}; +f1({ + x: 10, + y: 20, + moveBy: function (dx, dy) { + this.x += dx; + this.y += dy; + } +}); +var x1 = makeObject({ + data: { x: 0, y: 0 }, + methods: { + moveBy: function (dx, dy) { + this.x += dx; // Strongly typed this + this.y += dy; // Strongly typed this + } + } +}); +var x2 = makeObject2({ + data: { x: 0, y: 0 }, + methods: { + moveBy: function (dx, dy) { + this.x += dx; // Strongly typed this + this.y += dy; // Strongly typed this + } + } +}); +var vue = new Vue({ + data: function () { return ({ x: 1, y: 2 }); }, + methods: { + f: function (x) { + return this.x; + } + }, + computed: { + test: function () { + return this.x; + }, + hello: { + get: function () { + return "hi"; + }, + set: function (value) { + } + } + } +}); +vue; +vue.x; +vue.f("abc"); +vue.test; +vue.hello; + + +//// [thisTypeInObjectLiterals2.d.ts] +declare let obj1: { + a: number; + f(): number; + b: string; + c: { + g(): void; + }; + readonly d: number; + e: string; +}; +declare type Point = { + x: number; + y: number; + moveBy(dx: number, dy: number): void; +}; +declare let p1: Point; +declare function f1(p: Point): void; +declare type ObjectDescriptor = { + data?: D; + methods?: M & ThisType; +}; +declare function makeObject(desc: ObjectDescriptor): D & M; +declare let x1: { + x: number; + y: number; +} & { + moveBy(dx: number, dy: number): void; +}; +declare type ObjectDescriptor2 = ThisType & { + data?: D; + methods?: M; +}; +declare function makeObject2(desc: ObjectDescriptor): D & M; +declare let x2: { + x: number; + y: number; +} & { + moveBy(dx: number, dy: number): void; +}; +declare type Accessors = { + [K in keyof T]: (() => T[K]) | Computed; +}; +declare type Dictionary = { + [x: string]: T; +}; +declare type Computed = { + get?(): T; + set?(value: T): void; +}; +declare type VueOptions = ThisType & { + data?: D | (() => D); + methods?: M; + computed?: Accessors

; +}; +declare const Vue: new (options: VueOptions) => D & M & P; +declare let vue: { + x: number; + y: number; +} & { + f(x: string): number; +} & { + test: number; + hello: string; +}; diff --git a/tests/baselines/reference/thisTypeInObjectLiterals2.symbols b/tests/baselines/reference/thisTypeInObjectLiterals2.symbols new file mode 100644 index 00000000000..ef72c320cce --- /dev/null +++ b/tests/baselines/reference/thisTypeInObjectLiterals2.symbols @@ -0,0 +1,410 @@ +=== tests/cases/conformance/types/thisType/thisTypeInObjectLiterals2.ts === + +// In methods of an object literal with no contextual type, 'this' has the type +// of the object literal. + +let obj1 = { +>obj1 : Symbol(obj1, Decl(thisTypeInObjectLiterals2.ts, 4, 3)) + + a: 1, +>a : Symbol(a, Decl(thisTypeInObjectLiterals2.ts, 4, 12)) + + f() { +>f : Symbol(f, Decl(thisTypeInObjectLiterals2.ts, 5, 9)) + + return this.a; +>this.a : Symbol(a, Decl(thisTypeInObjectLiterals2.ts, 4, 12)) +>this : Symbol(obj1, Decl(thisTypeInObjectLiterals2.ts, 4, 10)) +>a : Symbol(a, Decl(thisTypeInObjectLiterals2.ts, 4, 12)) + + }, + b: "hello", +>b : Symbol(b, Decl(thisTypeInObjectLiterals2.ts, 8, 6)) + + c: { +>c : Symbol(c, Decl(thisTypeInObjectLiterals2.ts, 9, 15)) + + g() { +>g : Symbol(g, Decl(thisTypeInObjectLiterals2.ts, 10, 8)) + + this.g(); +>this.g : Symbol(g, Decl(thisTypeInObjectLiterals2.ts, 10, 8)) +>this : Symbol(__object, Decl(thisTypeInObjectLiterals2.ts, 10, 6)) +>g : Symbol(g, Decl(thisTypeInObjectLiterals2.ts, 10, 8)) + } + }, + get d() { +>d : Symbol(d, Decl(thisTypeInObjectLiterals2.ts, 14, 6)) + + return this.a; +>this.a : Symbol(a, Decl(thisTypeInObjectLiterals2.ts, 4, 12)) +>this : Symbol(obj1, Decl(thisTypeInObjectLiterals2.ts, 4, 10)) +>a : Symbol(a, Decl(thisTypeInObjectLiterals2.ts, 4, 12)) + + }, + get e() { +>e : Symbol(e, Decl(thisTypeInObjectLiterals2.ts, 17, 6), Decl(thisTypeInObjectLiterals2.ts, 20, 6)) + + return this.b; +>this.b : Symbol(b, Decl(thisTypeInObjectLiterals2.ts, 8, 6)) +>this : Symbol(obj1, Decl(thisTypeInObjectLiterals2.ts, 4, 10)) +>b : Symbol(b, Decl(thisTypeInObjectLiterals2.ts, 8, 6)) + + }, + set e(value) { +>e : Symbol(e, Decl(thisTypeInObjectLiterals2.ts, 17, 6), Decl(thisTypeInObjectLiterals2.ts, 20, 6)) +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 21, 10)) + + this.b = value; +>this.b : Symbol(b, Decl(thisTypeInObjectLiterals2.ts, 8, 6)) +>this : Symbol(obj1, Decl(thisTypeInObjectLiterals2.ts, 4, 10)) +>b : Symbol(b, Decl(thisTypeInObjectLiterals2.ts, 8, 6)) +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 21, 10)) + } +}; + +// In methods of an object literal with a contextual type, 'this' has the +// contextual type. + +type Point = { +>Point : Symbol(Point, Decl(thisTypeInObjectLiterals2.ts, 24, 2)) + + x: number; +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) + + y: number; +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14)) + + moveBy(dx: number, dy: number): void; +>moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 32, 11)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 32, 22)) +} + +let p1: Point = { +>p1 : Symbol(p1, Decl(thisTypeInObjectLiterals2.ts, 35, 3)) +>Point : Symbol(Point, Decl(thisTypeInObjectLiterals2.ts, 24, 2)) + + x: 10, +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 35, 17)) + + y: 20, +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 36, 10)) + + moveBy(dx, dy) { +>moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 37, 10)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 38, 11)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 38, 14)) + + this.x += dx; +>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 38, 11)) + + this.y += dy; +>this.y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 38, 14)) + } +}; + +declare function f1(p: Point): void; +>f1 : Symbol(f1, Decl(thisTypeInObjectLiterals2.ts, 42, 2)) +>p : Symbol(p, Decl(thisTypeInObjectLiterals2.ts, 44, 20)) +>Point : Symbol(Point, Decl(thisTypeInObjectLiterals2.ts, 24, 2)) + +f1({ +>f1 : Symbol(f1, Decl(thisTypeInObjectLiterals2.ts, 42, 2)) + + x: 10, +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 46, 4)) + + y: 20, +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 47, 10)) + + moveBy(dx, dy) { +>moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 48, 10)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 49, 11)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 49, 14)) + + this.x += dx; +>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 49, 11)) + + this.y += dy; +>this.y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 49, 14)) + } +}); + +// In methods of an object literal with a contextual type that includes some +// ThisType, 'this' is of type T. + +type ObjectDescriptor = { +>ObjectDescriptor : Symbol(ObjectDescriptor, Decl(thisTypeInObjectLiterals2.ts, 53, 3)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 58, 22)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 58, 24)) + + data?: D; +>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 58, 31)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 58, 22)) + + methods?: M & ThisType; // Type of 'this' in methods is D & M +>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 59, 13)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 58, 24)) +>ThisType : Symbol(ThisType, Decl(lib.d.ts, --, --)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 58, 22)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 58, 24)) +} + +declare function makeObject(desc: ObjectDescriptor): D & M; +>makeObject : Symbol(makeObject, Decl(thisTypeInObjectLiterals2.ts, 61, 1)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 63, 28)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 63, 30)) +>desc : Symbol(desc, Decl(thisTypeInObjectLiterals2.ts, 63, 34)) +>ObjectDescriptor : Symbol(ObjectDescriptor, Decl(thisTypeInObjectLiterals2.ts, 53, 3)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 63, 28)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 63, 30)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 63, 28)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 63, 30)) + +let x1 = makeObject({ +>x1 : Symbol(x1, Decl(thisTypeInObjectLiterals2.ts, 65, 3)) +>makeObject : Symbol(makeObject, Decl(thisTypeInObjectLiterals2.ts, 61, 1)) + + data: { x: 0, y: 0 }, +>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 65, 21)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 66, 11)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 66, 17)) + + methods: { +>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 66, 25)) + + moveBy(dx: number, dy: number) { +>moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 67, 14)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 68, 15)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 68, 26)) + + this.x += dx; // Strongly typed this +>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 66, 11)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 66, 11)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 68, 15)) + + this.y += dy; // Strongly typed this +>this.y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 66, 17)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 66, 17)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 68, 26)) + } + } +}); + +// In methods contained in an object literal with a contextual type that includes +// some ThisType, 'this' is of type T. + +type ObjectDescriptor2 = ThisType & { +>ObjectDescriptor2 : Symbol(ObjectDescriptor2, Decl(thisTypeInObjectLiterals2.ts, 73, 3)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 78, 23)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 78, 25)) +>ThisType : Symbol(ThisType, Decl(lib.d.ts, --, --)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 78, 23)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 78, 25)) + + data?: D; +>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 78, 50)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 78, 23)) + + methods?: M; +>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 79, 13)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 78, 25)) +} + +declare function makeObject2(desc: ObjectDescriptor): D & M; +>makeObject2 : Symbol(makeObject2, Decl(thisTypeInObjectLiterals2.ts, 81, 1)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 83, 29)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 83, 31)) +>desc : Symbol(desc, Decl(thisTypeInObjectLiterals2.ts, 83, 35)) +>ObjectDescriptor : Symbol(ObjectDescriptor, Decl(thisTypeInObjectLiterals2.ts, 53, 3)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 83, 29)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 83, 31)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 83, 29)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 83, 31)) + +let x2 = makeObject2({ +>x2 : Symbol(x2, Decl(thisTypeInObjectLiterals2.ts, 85, 3)) +>makeObject2 : Symbol(makeObject2, Decl(thisTypeInObjectLiterals2.ts, 81, 1)) + + data: { x: 0, y: 0 }, +>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 85, 22)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 86, 11)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 86, 17)) + + methods: { +>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 86, 25)) + + moveBy(dx: number, dy: number) { +>moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 87, 14)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 88, 15)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 88, 26)) + + this.x += dx; // Strongly typed this +>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 86, 11)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 86, 11)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 88, 15)) + + this.y += dy; // Strongly typed this +>this.y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 86, 17)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 86, 17)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 88, 26)) + } + } +}); + +// Proof of concept for typing of Vue.js + +type Accessors = { [K in keyof T]: (() => T[K]) | Computed }; +>Accessors : Symbol(Accessors, Decl(thisTypeInObjectLiterals2.ts, 93, 3)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 97, 15)) +>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 97, 23)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 97, 15)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 97, 15)) +>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 97, 23)) +>Computed : Symbol(Computed, Decl(thisTypeInObjectLiterals2.ts, 99, 39)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 97, 15)) +>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 97, 23)) + +type Dictionary = { [x: string]: T } +>Dictionary : Symbol(Dictionary, Decl(thisTypeInObjectLiterals2.ts, 97, 70)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 99, 16)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 99, 24)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 99, 16)) + +type Computed = { +>Computed : Symbol(Computed, Decl(thisTypeInObjectLiterals2.ts, 99, 39)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 101, 14)) + + get?(): T; +>get : Symbol(get, Decl(thisTypeInObjectLiterals2.ts, 101, 20)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 101, 14)) + + set?(value: T): void; +>set : Symbol(set, Decl(thisTypeInObjectLiterals2.ts, 102, 14)) +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 103, 9)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 101, 14)) +} + +type VueOptions = ThisType & { +>VueOptions : Symbol(VueOptions, Decl(thisTypeInObjectLiterals2.ts, 104, 1)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 106, 16)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 106, 18)) +>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 106, 21)) +>ThisType : Symbol(ThisType, Decl(lib.d.ts, --, --)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 106, 16)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 106, 18)) +>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 106, 21)) + + data?: D | (() => D); +>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 106, 50)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 106, 16)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 106, 16)) + + methods?: M; +>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 107, 25)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 106, 18)) + + computed?: Accessors

; +>computed : Symbol(computed, Decl(thisTypeInObjectLiterals2.ts, 108, 16)) +>Accessors : Symbol(Accessors, Decl(thisTypeInObjectLiterals2.ts, 93, 3)) +>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 106, 21)) +} + +declare const Vue: new (options: VueOptions) => D & M & P; +>Vue : Symbol(Vue, Decl(thisTypeInObjectLiterals2.ts, 112, 13)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 112, 24)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 112, 26)) +>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 112, 29)) +>options : Symbol(options, Decl(thisTypeInObjectLiterals2.ts, 112, 33)) +>VueOptions : Symbol(VueOptions, Decl(thisTypeInObjectLiterals2.ts, 104, 1)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 112, 24)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 112, 26)) +>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 112, 29)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 112, 24)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 112, 26)) +>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 112, 29)) + +let vue = new Vue({ +>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 114, 3)) +>Vue : Symbol(Vue, Decl(thisTypeInObjectLiterals2.ts, 112, 13)) + + data: () => ({ x: 1, y: 2 }), +>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 114, 19)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 115, 18)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 115, 24)) + + methods: { +>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 115, 33)) + + f(x: string) { +>f : Symbol(f, Decl(thisTypeInObjectLiterals2.ts, 116, 14)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 117, 10)) + + return this.x; +>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 115, 18)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 115, 18)) + } + }, + computed: { +>computed : Symbol(computed, Decl(thisTypeInObjectLiterals2.ts, 120, 6)) + + test(): number { +>test : Symbol(test, Decl(thisTypeInObjectLiterals2.ts, 121, 15)) + + return this.x; +>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 115, 18)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 115, 18)) + + }, + hello: { +>hello : Symbol(hello, Decl(thisTypeInObjectLiterals2.ts, 124, 10)) + + get() { +>get : Symbol(get, Decl(thisTypeInObjectLiterals2.ts, 125, 16)) + + return "hi"; + }, + set(value: string) { +>set : Symbol(set, Decl(thisTypeInObjectLiterals2.ts, 128, 14)) +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 129, 16)) + } + } + } +}); + +vue; +>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 114, 3)) + +vue.x; +>vue.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 115, 18)) +>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 114, 3)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 115, 18)) + +vue.f("abc"); +>vue.f : Symbol(f, Decl(thisTypeInObjectLiterals2.ts, 116, 14)) +>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 114, 3)) +>f : Symbol(f, Decl(thisTypeInObjectLiterals2.ts, 116, 14)) + +vue.test; +>vue.test : Symbol(test, Decl(thisTypeInObjectLiterals2.ts, 121, 15)) +>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 114, 3)) +>test : Symbol(test, Decl(thisTypeInObjectLiterals2.ts, 121, 15)) + +vue.hello; +>vue.hello : Symbol(hello, Decl(thisTypeInObjectLiterals2.ts, 124, 10)) +>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 114, 3)) +>hello : Symbol(hello, Decl(thisTypeInObjectLiterals2.ts, 124, 10)) + diff --git a/tests/baselines/reference/thisTypeInObjectLiterals2.types b/tests/baselines/reference/thisTypeInObjectLiterals2.types new file mode 100644 index 00000000000..39fd922f617 --- /dev/null +++ b/tests/baselines/reference/thisTypeInObjectLiterals2.types @@ -0,0 +1,463 @@ +=== tests/cases/conformance/types/thisType/thisTypeInObjectLiterals2.ts === + +// In methods of an object literal with no contextual type, 'this' has the type +// of the object literal. + +let obj1 = { +>obj1 : { a: number; f(): number; b: string; c: { g(): void; }; readonly d: number; e: string; } +>{ a: 1, f() { return this.a; }, b: "hello", c: { g() { this.g(); } }, get d() { return this.a; }, get e() { return this.b; }, set e(value) { this.b = value; }} : { a: number; f(): number; b: string; c: { g(): void; }; readonly d: number; e: string; } + + a: 1, +>a : number +>1 : 1 + + f() { +>f : () => number + + return this.a; +>this.a : number +>this : { a: number; f(): number; b: string; c: { g(): void; }; readonly d: number; e: string; } +>a : number + + }, + b: "hello", +>b : string +>"hello" : "hello" + + c: { +>c : { g(): void; } +>{ g() { this.g(); } } : { g(): void; } + + g() { +>g : () => void + + this.g(); +>this.g() : void +>this.g : () => void +>this : { g(): void; } +>g : () => void + } + }, + get d() { +>d : number + + return this.a; +>this.a : number +>this : { a: number; f(): number; b: string; c: { g(): void; }; readonly d: number; e: string; } +>a : number + + }, + get e() { +>e : string + + return this.b; +>this.b : string +>this : { a: number; f(): number; b: string; c: { g(): void; }; readonly d: number; e: string; } +>b : string + + }, + set e(value) { +>e : string +>value : string + + this.b = value; +>this.b = value : string +>this.b : string +>this : { a: number; f(): number; b: string; c: { g(): void; }; readonly d: number; e: string; } +>b : string +>value : string + } +}; + +// In methods of an object literal with a contextual type, 'this' has the +// contextual type. + +type Point = { +>Point : Point + + x: number; +>x : number + + y: number; +>y : number + + moveBy(dx: number, dy: number): void; +>moveBy : (dx: number, dy: number) => void +>dx : number +>dy : number +} + +let p1: Point = { +>p1 : Point +>Point : Point +>{ x: 10, y: 20, moveBy(dx, dy) { this.x += dx; this.y += dy; }} : { x: number; y: number; moveBy(dx: number, dy: number): void; } + + x: 10, +>x : number +>10 : 10 + + y: 20, +>y : number +>20 : 20 + + moveBy(dx, dy) { +>moveBy : (dx: number, dy: number) => void +>dx : number +>dy : number + + this.x += dx; +>this.x += dx : number +>this.x : number +>this : Point +>x : number +>dx : number + + this.y += dy; +>this.y += dy : number +>this.y : number +>this : Point +>y : number +>dy : number + } +}; + +declare function f1(p: Point): void; +>f1 : (p: Point) => void +>p : Point +>Point : Point + +f1({ +>f1({ x: 10, y: 20, moveBy(dx, dy) { this.x += dx; this.y += dy; }}) : void +>f1 : (p: Point) => void +>{ x: 10, y: 20, moveBy(dx, dy) { this.x += dx; this.y += dy; }} : { x: number; y: number; moveBy(dx: number, dy: number): void; } + + x: 10, +>x : number +>10 : 10 + + y: 20, +>y : number +>20 : 20 + + moveBy(dx, dy) { +>moveBy : (dx: number, dy: number) => void +>dx : number +>dy : number + + this.x += dx; +>this.x += dx : number +>this.x : number +>this : Point +>x : number +>dx : number + + this.y += dy; +>this.y += dy : number +>this.y : number +>this : Point +>y : number +>dy : number + } +}); + +// In methods of an object literal with a contextual type that includes some +// ThisType, 'this' is of type T. + +type ObjectDescriptor = { +>ObjectDescriptor : ObjectDescriptor +>D : D +>M : M + + data?: D; +>data : D +>D : D + + methods?: M & ThisType; // Type of 'this' in methods is D & M +>methods : M & ThisType +>M : M +>ThisType : ThisType +>D : D +>M : M +} + +declare function makeObject(desc: ObjectDescriptor): D & M; +>makeObject : (desc: ObjectDescriptor) => D & M +>D : D +>M : M +>desc : ObjectDescriptor +>ObjectDescriptor : ObjectDescriptor +>D : D +>M : M +>D : D +>M : M + +let x1 = makeObject({ +>x1 : { x: number; y: number; } & { moveBy(dx: number, dy: number): void; } +>makeObject({ data: { x: 0, y: 0 }, methods: { moveBy(dx: number, dy: number) { this.x += dx; // Strongly typed this this.y += dy; // Strongly typed this } }}) : { x: number; y: number; } & { moveBy(dx: number, dy: number): void; } +>makeObject : (desc: ObjectDescriptor) => D & M +>{ data: { x: 0, y: 0 }, methods: { moveBy(dx: number, dy: number) { this.x += dx; // Strongly typed this this.y += dy; // Strongly typed this } }} : { data: { x: number; y: number; }; methods: { moveBy(dx: number, dy: number): void; }; } + + data: { x: 0, y: 0 }, +>data : { x: number; y: number; } +>{ x: 0, y: 0 } : { x: number; y: number; } +>x : number +>0 : 0 +>y : number +>0 : 0 + + methods: { +>methods : { moveBy(dx: number, dy: number): void; } +>{ moveBy(dx: number, dy: number) { this.x += dx; // Strongly typed this this.y += dy; // Strongly typed this } } : { moveBy(dx: number, dy: number): void; } + + moveBy(dx: number, dy: number) { +>moveBy : (dx: number, dy: number) => void +>dx : number +>dy : number + + this.x += dx; // Strongly typed this +>this.x += dx : number +>this.x : number +>this : { x: number; y: number; } & { moveBy(dx: number, dy: number): void; } +>x : number +>dx : number + + this.y += dy; // Strongly typed this +>this.y += dy : number +>this.y : number +>this : { x: number; y: number; } & { moveBy(dx: number, dy: number): void; } +>y : number +>dy : number + } + } +}); + +// In methods contained in an object literal with a contextual type that includes +// some ThisType, 'this' is of type T. + +type ObjectDescriptor2 = ThisType & { +>ObjectDescriptor2 : ObjectDescriptor2 +>D : D +>M : M +>ThisType : ThisType +>D : D +>M : M + + data?: D; +>data : D +>D : D + + methods?: M; +>methods : M +>M : M +} + +declare function makeObject2(desc: ObjectDescriptor): D & M; +>makeObject2 : (desc: ObjectDescriptor) => D & M +>D : D +>M : M +>desc : ObjectDescriptor +>ObjectDescriptor : ObjectDescriptor +>D : D +>M : M +>D : D +>M : M + +let x2 = makeObject2({ +>x2 : { x: number; y: number; } & { moveBy(dx: number, dy: number): void; } +>makeObject2({ data: { x: 0, y: 0 }, methods: { moveBy(dx: number, dy: number) { this.x += dx; // Strongly typed this this.y += dy; // Strongly typed this } }}) : { x: number; y: number; } & { moveBy(dx: number, dy: number): void; } +>makeObject2 : (desc: ObjectDescriptor) => D & M +>{ data: { x: 0, y: 0 }, methods: { moveBy(dx: number, dy: number) { this.x += dx; // Strongly typed this this.y += dy; // Strongly typed this } }} : { data: { x: number; y: number; }; methods: { moveBy(dx: number, dy: number): void; }; } + + data: { x: 0, y: 0 }, +>data : { x: number; y: number; } +>{ x: 0, y: 0 } : { x: number; y: number; } +>x : number +>0 : 0 +>y : number +>0 : 0 + + methods: { +>methods : { moveBy(dx: number, dy: number): void; } +>{ moveBy(dx: number, dy: number) { this.x += dx; // Strongly typed this this.y += dy; // Strongly typed this } } : { moveBy(dx: number, dy: number): void; } + + moveBy(dx: number, dy: number) { +>moveBy : (dx: number, dy: number) => void +>dx : number +>dy : number + + this.x += dx; // Strongly typed this +>this.x += dx : number +>this.x : number +>this : { x: number; y: number; } & { moveBy(dx: number, dy: number): void; } +>x : number +>dx : number + + this.y += dy; // Strongly typed this +>this.y += dy : number +>this.y : number +>this : { x: number; y: number; } & { moveBy(dx: number, dy: number): void; } +>y : number +>dy : number + } + } +}); + +// Proof of concept for typing of Vue.js + +type Accessors = { [K in keyof T]: (() => T[K]) | Computed }; +>Accessors : Accessors +>T : T +>K : K +>T : T +>T : T +>K : K +>Computed : Computed +>T : T +>K : K + +type Dictionary = { [x: string]: T } +>Dictionary : Dictionary +>T : T +>x : string +>T : T + +type Computed = { +>Computed : Computed +>T : T + + get?(): T; +>get : () => T +>T : T + + set?(value: T): void; +>set : (value: T) => void +>value : T +>T : T +} + +type VueOptions = ThisType & { +>VueOptions : VueOptions +>D : D +>M : M +>P : P +>ThisType : ThisType +>D : D +>M : M +>P : P + + data?: D | (() => D); +>data : D | (() => D) +>D : D +>D : D + + methods?: M; +>methods : M +>M : M + + computed?: Accessors

; +>computed : Accessors

+>Accessors : Accessors +>P : P +} + +declare const Vue: new (options: VueOptions) => D & M & P; +>Vue : new (options: VueOptions) => D & M & P +>D : D +>M : M +>P : P +>options : VueOptions +>VueOptions : VueOptions +>D : D +>M : M +>P : P +>D : D +>M : M +>P : P + +let vue = new Vue({ +>vue : { x: number; y: number; } & { f(x: string): number; } & { test: number; hello: string; } +>new Vue({ data: () => ({ x: 1, y: 2 }), methods: { f(x: string) { return this.x; } }, computed: { test(): number { return this.x; }, hello: { get() { return "hi"; }, set(value: string) { } } }}) : { x: number; y: number; } & { f(x: string): number; } & { test: number; hello: string; } +>Vue : new (options: VueOptions) => D & M & P +>{ data: () => ({ x: 1, y: 2 }), methods: { f(x: string) { return this.x; } }, computed: { test(): number { return this.x; }, hello: { get() { return "hi"; }, set(value: string) { } } }} : { data: () => { x: number; y: number; }; methods: { f(x: string): number; }; computed: { test(): number; hello: { get(): string; set(value: string): void; }; }; } + + data: () => ({ x: 1, y: 2 }), +>data : () => { x: number; y: number; } +>() => ({ x: 1, y: 2 }) : () => { x: number; y: number; } +>({ x: 1, y: 2 }) : { x: number; y: number; } +>{ x: 1, y: 2 } : { x: number; y: number; } +>x : number +>1 : 1 +>y : number +>2 : 2 + + methods: { +>methods : { f(x: string): number; } +>{ f(x: string) { return this.x; } } : { f(x: string): number; } + + f(x: string) { +>f : (x: string) => number +>x : string + + return this.x; +>this.x : number +>this : { x: number; y: number; } & { f(x: string): number; } & { test: number; hello: string; } +>x : number + } + }, + computed: { +>computed : { test(): number; hello: { get(): string; set(value: string): void; }; } +>{ test(): number { return this.x; }, hello: { get() { return "hi"; }, set(value: string) { } } } : { test(): number; hello: { get(): string; set(value: string): void; }; } + + test(): number { +>test : () => number + + return this.x; +>this.x : number +>this : { x: number; y: number; } & { f(x: string): number; } & { test: number; hello: string; } +>x : number + + }, + hello: { +>hello : { get(): string; set(value: string): void; } +>{ get() { return "hi"; }, set(value: string) { } } : { get(): string; set(value: string): void; } + + get() { +>get : () => string + + return "hi"; +>"hi" : "hi" + + }, + set(value: string) { +>set : (value: string) => void +>value : string + } + } + } +}); + +vue; +>vue : { x: number; y: number; } & { f(x: string): number; } & { test: number; hello: string; } + +vue.x; +>vue.x : number +>vue : { x: number; y: number; } & { f(x: string): number; } & { test: number; hello: string; } +>x : number + +vue.f("abc"); +>vue.f("abc") : number +>vue.f : (x: string) => number +>vue : { x: number; y: number; } & { f(x: string): number; } & { test: number; hello: string; } +>f : (x: string) => number +>"abc" : "abc" + +vue.test; +>vue.test : number +>vue : { x: number; y: number; } & { f(x: string): number; } & { test: number; hello: string; } +>test : number + +vue.hello; +>vue.hello : string +>vue : { x: number; y: number; } & { f(x: string): number; } & { test: number; hello: string; } +>hello : string + diff --git a/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals2.ts b/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals2.ts new file mode 100644 index 00000000000..7358b47259c --- /dev/null +++ b/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals2.ts @@ -0,0 +1,144 @@ +// @declaration: true +// @noImplicitAny: true +// @noImplicitThis: true +// @target: es5 + +// In methods of an object literal with no contextual type, 'this' has the type +// of the object literal. + +let obj1 = { + a: 1, + f() { + return this.a; + }, + b: "hello", + c: { + g() { + this.g(); + } + }, + get d() { + return this.a; + }, + get e() { + return this.b; + }, + set e(value) { + this.b = value; + } +}; + +// In methods of an object literal with a contextual type, 'this' has the +// contextual type. + +type Point = { + x: number; + y: number; + moveBy(dx: number, dy: number): void; +} + +let p1: Point = { + x: 10, + y: 20, + moveBy(dx, dy) { + this.x += dx; + this.y += dy; + } +}; + +declare function f1(p: Point): void; + +f1({ + x: 10, + y: 20, + moveBy(dx, dy) { + this.x += dx; + this.y += dy; + } +}); + +// In methods of an object literal with a contextual type that includes some +// ThisType, 'this' is of type T. + +type ObjectDescriptor = { + data?: D; + methods?: M & ThisType; // Type of 'this' in methods is D & M +} + +declare function makeObject(desc: ObjectDescriptor): D & M; + +let x1 = makeObject({ + data: { x: 0, y: 0 }, + methods: { + moveBy(dx: number, dy: number) { + this.x += dx; // Strongly typed this + this.y += dy; // Strongly typed this + } + } +}); + +// In methods contained in an object literal with a contextual type that includes +// some ThisType, 'this' is of type T. + +type ObjectDescriptor2 = ThisType & { + data?: D; + methods?: M; +} + +declare function makeObject2(desc: ObjectDescriptor): D & M; + +let x2 = makeObject2({ + data: { x: 0, y: 0 }, + methods: { + moveBy(dx: number, dy: number) { + this.x += dx; // Strongly typed this + this.y += dy; // Strongly typed this + } + } +}); + +// Proof of concept for typing of Vue.js + +type Accessors = { [K in keyof T]: (() => T[K]) | Computed }; + +type Dictionary = { [x: string]: T } + +type Computed = { + get?(): T; + set?(value: T): void; +} + +type VueOptions = ThisType & { + data?: D | (() => D); + methods?: M; + computed?: Accessors

; +} + +declare const Vue: new (options: VueOptions) => D & M & P; + +let vue = new Vue({ + data: () => ({ x: 1, y: 2 }), + methods: { + f(x: string) { + return this.x; + } + }, + computed: { + test(): number { + return this.x; + }, + hello: { + get() { + return "hi"; + }, + set(value: string) { + } + } + } +}); + +vue; +vue.x; +vue.f("abc"); +vue.test; +vue.hello; From b977b8cc45d9c5fee51334507b95124cc393ab3b Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 27 Feb 2017 15:58:01 -0800 Subject: [PATCH 22/65] Respond to code review comments --- src/compiler/binder.ts | 5 +- src/compiler/checker.ts | 4 +- .../inferringClassMembersFromAssignments.js | 13 ++ ...ferringClassMembersFromAssignments.symbols | 120 +++++++++++------- ...inferringClassMembersFromAssignments.types | 28 ++++ .../inferringClassMembersFromAssignments.ts | 8 ++ 6 files changed, 123 insertions(+), 55 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 2fc7317884d..beba3224963 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2254,10 +2254,7 @@ namespace ts { // this.foo assignment in a JavaScript class // Bind this property to the containing class const containingClass = container.parent; - const symbol = hasModifier(container, ModifierFlags.Static) - ? declareSymbol(containingClass.symbol.exports, containingClass.symbol, node, SymbolFlags.Property, SymbolFlags.None) - : declareSymbol(containingClass.symbol.members, containingClass.symbol, node, SymbolFlags.Property, SymbolFlags.None); - + const symbol = declareSymbol(hasModifier(container, ModifierFlags.Static) ? containingClass.symbol.exports : containingClass.symbol.members, containingClass.symbol, node, SymbolFlags.Property, SymbolFlags.None); if (symbol) { // symbols declared through 'this' property assignements can be overwritten by subsequent method declarations (symbol as Symbol).isReplaceableByMethod = true; diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 93973fe71a8..aa8d42dd3c1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3472,7 +3472,7 @@ namespace ts { return undefined; } - function getWidendedTypeFromJSSpecialPropetyDeclarations(symbol: Symbol) { + function getWidenedTypeFromJSSpecialPropetyDeclarations(symbol: Symbol) { const types: Type[] = []; let definedInConstructor = false; let definedInMethod = false; @@ -3663,7 +3663,7 @@ namespace ts { // * className.prototype.method = expr if (declaration.kind === SyntaxKind.BinaryExpression || declaration.kind === SyntaxKind.PropertyAccessExpression && declaration.parent.kind === SyntaxKind.BinaryExpression) { - type = getWidendedTypeFromJSSpecialPropetyDeclarations(symbol); + type = getWidenedTypeFromJSSpecialPropetyDeclarations(symbol); } else { type = getWidenedTypeForVariableLikeDeclaration(declaration, /*reportErrors*/ true); diff --git a/tests/baselines/reference/inferringClassMembersFromAssignments.js b/tests/baselines/reference/inferringClassMembersFromAssignments.js index 6513a3b03a6..a7b9e4ff8f0 100644 --- a/tests/baselines/reference/inferringClassMembersFromAssignments.js +++ b/tests/baselines/reference/inferringClassMembersFromAssignments.js @@ -10,6 +10,7 @@ class C { else { this.inConstructor = "string" } + this.inMultiple = 0; } method() { if (Math.random()) { @@ -18,6 +19,7 @@ class C { else { this.inMethod = "string" } + this.inMultiple = "string"; } get() { if (Math.random()) { @@ -26,6 +28,7 @@ class C { else { this.inGetter = "string" } + this.inMultiple = false; } set() { if (Math.random()) { @@ -73,6 +76,11 @@ var stringOrNumberOrUndefined = c.inMethod; var stringOrNumberOrUndefined = c.inGetter; var stringOrNumberOrUndefined = c.inSetter; +var stringOrNumberOrBoolean: string | number | boolean; + +var stringOrNumberOrBoolean = c.inMultiple; + + var stringOrNumberOrUndefined = C.inStaticMethod; var stringOrNumberOrUndefined = C.inStaticGetter; var stringOrNumberOrUndefined = C.inStaticSetter; @@ -87,6 +95,7 @@ var C = (function () { else { this.inConstructor = "string"; } + this.inMultiple = 0; } C.prototype.method = function () { if (Math.random()) { @@ -95,6 +104,7 @@ var C = (function () { else { this.inMethod = "string"; } + this.inMultiple = "string"; }; C.prototype.get = function () { if (Math.random()) { @@ -103,6 +113,7 @@ var C = (function () { else { this.inGetter = "string"; } + this.inMultiple = false; }; C.prototype.set = function () { if (Math.random()) { @@ -145,6 +156,8 @@ var stringOrNumberOrUndefined; var stringOrNumberOrUndefined = c.inMethod; var stringOrNumberOrUndefined = c.inGetter; var stringOrNumberOrUndefined = c.inSetter; +var stringOrNumberOrBoolean; +var stringOrNumberOrBoolean = c.inMultiple; var stringOrNumberOrUndefined = C.inStaticMethod; var stringOrNumberOrUndefined = C.inStaticGetter; var stringOrNumberOrUndefined = C.inStaticSetter; diff --git a/tests/baselines/reference/inferringClassMembersFromAssignments.symbols b/tests/baselines/reference/inferringClassMembersFromAssignments.symbols index d96d4ff359f..9951339f8a8 100644 --- a/tests/baselines/reference/inferringClassMembersFromAssignments.symbols +++ b/tests/baselines/reference/inferringClassMembersFromAssignments.symbols @@ -20,9 +20,13 @@ class C { >this : Symbol(C, Decl(a.js, 0, 0)) >inConstructor : Symbol(C.inConstructor, Decl(a.js, 3, 28), Decl(a.js, 6, 14)) } + this.inMultiple = 0; +>this.inMultiple : Symbol(C.inMultiple, Decl(a.js, 8, 9), Decl(a.js, 17, 9), Decl(a.js, 26, 9)) +>this : Symbol(C, Decl(a.js, 0, 0)) +>inMultiple : Symbol(C.inMultiple, Decl(a.js, 8, 9), Decl(a.js, 17, 9), Decl(a.js, 26, 9)) } method() { ->method : Symbol(C.method, Decl(a.js, 9, 5)) +>method : Symbol(C.method, Decl(a.js, 10, 5)) if (Math.random()) { >Math.random : Symbol(Math.random, Decl(lib.d.ts, --, --)) @@ -30,19 +34,23 @@ class C { >random : Symbol(Math.random, Decl(lib.d.ts, --, --)) this.inMethod = 0; ->this.inMethod : Symbol(C.inMethod, Decl(a.js, 11, 28), Decl(a.js, 14, 14)) +>this.inMethod : Symbol(C.inMethod, Decl(a.js, 12, 28), Decl(a.js, 15, 14)) >this : Symbol(C, Decl(a.js, 0, 0)) ->inMethod : Symbol(C.inMethod, Decl(a.js, 11, 28), Decl(a.js, 14, 14)) +>inMethod : Symbol(C.inMethod, Decl(a.js, 12, 28), Decl(a.js, 15, 14)) } else { this.inMethod = "string" ->this.inMethod : Symbol(C.inMethod, Decl(a.js, 11, 28), Decl(a.js, 14, 14)) +>this.inMethod : Symbol(C.inMethod, Decl(a.js, 12, 28), Decl(a.js, 15, 14)) >this : Symbol(C, Decl(a.js, 0, 0)) ->inMethod : Symbol(C.inMethod, Decl(a.js, 11, 28), Decl(a.js, 14, 14)) +>inMethod : Symbol(C.inMethod, Decl(a.js, 12, 28), Decl(a.js, 15, 14)) } + this.inMultiple = "string"; +>this.inMultiple : Symbol(C.inMultiple, Decl(a.js, 8, 9), Decl(a.js, 17, 9), Decl(a.js, 26, 9)) +>this : Symbol(C, Decl(a.js, 0, 0)) +>inMultiple : Symbol(C.inMultiple, Decl(a.js, 8, 9), Decl(a.js, 17, 9), Decl(a.js, 26, 9)) } get() { ->get : Symbol(C.get, Decl(a.js, 17, 5)) +>get : Symbol(C.get, Decl(a.js, 19, 5)) if (Math.random()) { >Math.random : Symbol(Math.random, Decl(lib.d.ts, --, --)) @@ -50,19 +58,23 @@ class C { >random : Symbol(Math.random, Decl(lib.d.ts, --, --)) this.inGetter = 0; ->this.inGetter : Symbol(C.inGetter, Decl(a.js, 19, 28), Decl(a.js, 22, 14)) +>this.inGetter : Symbol(C.inGetter, Decl(a.js, 21, 28), Decl(a.js, 24, 14)) >this : Symbol(C, Decl(a.js, 0, 0)) ->inGetter : Symbol(C.inGetter, Decl(a.js, 19, 28), Decl(a.js, 22, 14)) +>inGetter : Symbol(C.inGetter, Decl(a.js, 21, 28), Decl(a.js, 24, 14)) } else { this.inGetter = "string" ->this.inGetter : Symbol(C.inGetter, Decl(a.js, 19, 28), Decl(a.js, 22, 14)) +>this.inGetter : Symbol(C.inGetter, Decl(a.js, 21, 28), Decl(a.js, 24, 14)) >this : Symbol(C, Decl(a.js, 0, 0)) ->inGetter : Symbol(C.inGetter, Decl(a.js, 19, 28), Decl(a.js, 22, 14)) +>inGetter : Symbol(C.inGetter, Decl(a.js, 21, 28), Decl(a.js, 24, 14)) } + this.inMultiple = false; +>this.inMultiple : Symbol(C.inMultiple, Decl(a.js, 8, 9), Decl(a.js, 17, 9), Decl(a.js, 26, 9)) +>this : Symbol(C, Decl(a.js, 0, 0)) +>inMultiple : Symbol(C.inMultiple, Decl(a.js, 8, 9), Decl(a.js, 17, 9), Decl(a.js, 26, 9)) } set() { ->set : Symbol(C.set, Decl(a.js, 25, 5)) +>set : Symbol(C.set, Decl(a.js, 28, 5)) if (Math.random()) { >Math.random : Symbol(Math.random, Decl(lib.d.ts, --, --)) @@ -70,19 +82,19 @@ class C { >random : Symbol(Math.random, Decl(lib.d.ts, --, --)) this.inSetter = 0; ->this.inSetter : Symbol(C.inSetter, Decl(a.js, 27, 28), Decl(a.js, 30, 14)) +>this.inSetter : Symbol(C.inSetter, Decl(a.js, 30, 28), Decl(a.js, 33, 14)) >this : Symbol(C, Decl(a.js, 0, 0)) ->inSetter : Symbol(C.inSetter, Decl(a.js, 27, 28), Decl(a.js, 30, 14)) +>inSetter : Symbol(C.inSetter, Decl(a.js, 30, 28), Decl(a.js, 33, 14)) } else { this.inSetter = "string" ->this.inSetter : Symbol(C.inSetter, Decl(a.js, 27, 28), Decl(a.js, 30, 14)) +>this.inSetter : Symbol(C.inSetter, Decl(a.js, 30, 28), Decl(a.js, 33, 14)) >this : Symbol(C, Decl(a.js, 0, 0)) ->inSetter : Symbol(C.inSetter, Decl(a.js, 27, 28), Decl(a.js, 30, 14)) +>inSetter : Symbol(C.inSetter, Decl(a.js, 30, 28), Decl(a.js, 33, 14)) } } static method() { ->method : Symbol(C.method, Decl(a.js, 33, 5)) +>method : Symbol(C.method, Decl(a.js, 36, 5)) if (Math.random()) { >Math.random : Symbol(Math.random, Decl(lib.d.ts, --, --)) @@ -90,19 +102,19 @@ class C { >random : Symbol(Math.random, Decl(lib.d.ts, --, --)) this.inStaticMethod = 0; ->this.inStaticMethod : Symbol(C.inStaticMethod, Decl(a.js, 35, 28), Decl(a.js, 38, 14)) +>this.inStaticMethod : Symbol(C.inStaticMethod, Decl(a.js, 38, 28), Decl(a.js, 41, 14)) >this : Symbol(C, Decl(a.js, 0, 0)) ->inStaticMethod : Symbol(C.inStaticMethod, Decl(a.js, 35, 28), Decl(a.js, 38, 14)) +>inStaticMethod : Symbol(C.inStaticMethod, Decl(a.js, 38, 28), Decl(a.js, 41, 14)) } else { this.inStaticMethod = "string" ->this.inStaticMethod : Symbol(C.inStaticMethod, Decl(a.js, 35, 28), Decl(a.js, 38, 14)) +>this.inStaticMethod : Symbol(C.inStaticMethod, Decl(a.js, 38, 28), Decl(a.js, 41, 14)) >this : Symbol(C, Decl(a.js, 0, 0)) ->inStaticMethod : Symbol(C.inStaticMethod, Decl(a.js, 35, 28), Decl(a.js, 38, 14)) +>inStaticMethod : Symbol(C.inStaticMethod, Decl(a.js, 38, 28), Decl(a.js, 41, 14)) } } static get() { ->get : Symbol(C.get, Decl(a.js, 41, 5)) +>get : Symbol(C.get, Decl(a.js, 44, 5)) if (Math.random()) { >Math.random : Symbol(Math.random, Decl(lib.d.ts, --, --)) @@ -110,19 +122,19 @@ class C { >random : Symbol(Math.random, Decl(lib.d.ts, --, --)) this.inStaticGetter = 0; ->this.inStaticGetter : Symbol(C.inStaticGetter, Decl(a.js, 43, 28), Decl(a.js, 46, 14)) +>this.inStaticGetter : Symbol(C.inStaticGetter, Decl(a.js, 46, 28), Decl(a.js, 49, 14)) >this : Symbol(C, Decl(a.js, 0, 0)) ->inStaticGetter : Symbol(C.inStaticGetter, Decl(a.js, 43, 28), Decl(a.js, 46, 14)) +>inStaticGetter : Symbol(C.inStaticGetter, Decl(a.js, 46, 28), Decl(a.js, 49, 14)) } else { this.inStaticGetter = "string" ->this.inStaticGetter : Symbol(C.inStaticGetter, Decl(a.js, 43, 28), Decl(a.js, 46, 14)) +>this.inStaticGetter : Symbol(C.inStaticGetter, Decl(a.js, 46, 28), Decl(a.js, 49, 14)) >this : Symbol(C, Decl(a.js, 0, 0)) ->inStaticGetter : Symbol(C.inStaticGetter, Decl(a.js, 43, 28), Decl(a.js, 46, 14)) +>inStaticGetter : Symbol(C.inStaticGetter, Decl(a.js, 46, 28), Decl(a.js, 49, 14)) } } static set() { ->set : Symbol(C.set, Decl(a.js, 49, 5)) +>set : Symbol(C.set, Decl(a.js, 52, 5)) if (Math.random()) { >Math.random : Symbol(Math.random, Decl(lib.d.ts, --, --)) @@ -130,15 +142,15 @@ class C { >random : Symbol(Math.random, Decl(lib.d.ts, --, --)) this.inStaticSetter = 0; ->this.inStaticSetter : Symbol(C.inStaticSetter, Decl(a.js, 51, 28), Decl(a.js, 54, 14)) +>this.inStaticSetter : Symbol(C.inStaticSetter, Decl(a.js, 54, 28), Decl(a.js, 57, 14)) >this : Symbol(C, Decl(a.js, 0, 0)) ->inStaticSetter : Symbol(C.inStaticSetter, Decl(a.js, 51, 28), Decl(a.js, 54, 14)) +>inStaticSetter : Symbol(C.inStaticSetter, Decl(a.js, 54, 28), Decl(a.js, 57, 14)) } else { this.inStaticSetter = "string" ->this.inStaticSetter : Symbol(C.inStaticSetter, Decl(a.js, 51, 28), Decl(a.js, 54, 14)) +>this.inStaticSetter : Symbol(C.inStaticSetter, Decl(a.js, 54, 28), Decl(a.js, 57, 14)) >this : Symbol(C, Decl(a.js, 0, 0)) ->inStaticSetter : Symbol(C.inStaticSetter, Decl(a.js, 51, 28), Decl(a.js, 54, 14)) +>inStaticSetter : Symbol(C.inStaticSetter, Decl(a.js, 54, 28), Decl(a.js, 57, 14)) } } } @@ -158,41 +170,51 @@ var stringOrNumber = c.inConstructor; >inConstructor : Symbol(C.inConstructor, Decl(a.js, 3, 28), Decl(a.js, 6, 14)) var stringOrNumberOrUndefined: string | number | undefined; ->stringOrNumberOrUndefined : Symbol(stringOrNumberOrUndefined, Decl(b.ts, 5, 3), Decl(b.ts, 7, 3), Decl(b.ts, 8, 3), Decl(b.ts, 9, 3), Decl(b.ts, 11, 3), Decl(b.ts, 12, 3), Decl(b.ts, 13, 3)) +>stringOrNumberOrUndefined : Symbol(stringOrNumberOrUndefined, Decl(b.ts, 5, 3), Decl(b.ts, 7, 3), Decl(b.ts, 8, 3), Decl(b.ts, 9, 3), Decl(b.ts, 16, 3), Decl(b.ts, 17, 3), Decl(b.ts, 18, 3)) var stringOrNumberOrUndefined = c.inMethod; ->stringOrNumberOrUndefined : Symbol(stringOrNumberOrUndefined, Decl(b.ts, 5, 3), Decl(b.ts, 7, 3), Decl(b.ts, 8, 3), Decl(b.ts, 9, 3), Decl(b.ts, 11, 3), Decl(b.ts, 12, 3), Decl(b.ts, 13, 3)) ->c.inMethod : Symbol(C.inMethod, Decl(a.js, 11, 28), Decl(a.js, 14, 14)) +>stringOrNumberOrUndefined : Symbol(stringOrNumberOrUndefined, Decl(b.ts, 5, 3), Decl(b.ts, 7, 3), Decl(b.ts, 8, 3), Decl(b.ts, 9, 3), Decl(b.ts, 16, 3), Decl(b.ts, 17, 3), Decl(b.ts, 18, 3)) +>c.inMethod : Symbol(C.inMethod, Decl(a.js, 12, 28), Decl(a.js, 15, 14)) >c : Symbol(c, Decl(b.ts, 0, 3)) ->inMethod : Symbol(C.inMethod, Decl(a.js, 11, 28), Decl(a.js, 14, 14)) +>inMethod : Symbol(C.inMethod, Decl(a.js, 12, 28), Decl(a.js, 15, 14)) var stringOrNumberOrUndefined = c.inGetter; ->stringOrNumberOrUndefined : Symbol(stringOrNumberOrUndefined, Decl(b.ts, 5, 3), Decl(b.ts, 7, 3), Decl(b.ts, 8, 3), Decl(b.ts, 9, 3), Decl(b.ts, 11, 3), Decl(b.ts, 12, 3), Decl(b.ts, 13, 3)) ->c.inGetter : Symbol(C.inGetter, Decl(a.js, 19, 28), Decl(a.js, 22, 14)) +>stringOrNumberOrUndefined : Symbol(stringOrNumberOrUndefined, Decl(b.ts, 5, 3), Decl(b.ts, 7, 3), Decl(b.ts, 8, 3), Decl(b.ts, 9, 3), Decl(b.ts, 16, 3), Decl(b.ts, 17, 3), Decl(b.ts, 18, 3)) +>c.inGetter : Symbol(C.inGetter, Decl(a.js, 21, 28), Decl(a.js, 24, 14)) >c : Symbol(c, Decl(b.ts, 0, 3)) ->inGetter : Symbol(C.inGetter, Decl(a.js, 19, 28), Decl(a.js, 22, 14)) +>inGetter : Symbol(C.inGetter, Decl(a.js, 21, 28), Decl(a.js, 24, 14)) var stringOrNumberOrUndefined = c.inSetter; ->stringOrNumberOrUndefined : Symbol(stringOrNumberOrUndefined, Decl(b.ts, 5, 3), Decl(b.ts, 7, 3), Decl(b.ts, 8, 3), Decl(b.ts, 9, 3), Decl(b.ts, 11, 3), Decl(b.ts, 12, 3), Decl(b.ts, 13, 3)) ->c.inSetter : Symbol(C.inSetter, Decl(a.js, 27, 28), Decl(a.js, 30, 14)) +>stringOrNumberOrUndefined : Symbol(stringOrNumberOrUndefined, Decl(b.ts, 5, 3), Decl(b.ts, 7, 3), Decl(b.ts, 8, 3), Decl(b.ts, 9, 3), Decl(b.ts, 16, 3), Decl(b.ts, 17, 3), Decl(b.ts, 18, 3)) +>c.inSetter : Symbol(C.inSetter, Decl(a.js, 30, 28), Decl(a.js, 33, 14)) >c : Symbol(c, Decl(b.ts, 0, 3)) ->inSetter : Symbol(C.inSetter, Decl(a.js, 27, 28), Decl(a.js, 30, 14)) +>inSetter : Symbol(C.inSetter, Decl(a.js, 30, 28), Decl(a.js, 33, 14)) + +var stringOrNumberOrBoolean: string | number | boolean; +>stringOrNumberOrBoolean : Symbol(stringOrNumberOrBoolean, Decl(b.ts, 11, 3), Decl(b.ts, 13, 3)) + +var stringOrNumberOrBoolean = c.inMultiple; +>stringOrNumberOrBoolean : Symbol(stringOrNumberOrBoolean, Decl(b.ts, 11, 3), Decl(b.ts, 13, 3)) +>c.inMultiple : Symbol(C.inMultiple, Decl(a.js, 8, 9), Decl(a.js, 17, 9), Decl(a.js, 26, 9)) +>c : Symbol(c, Decl(b.ts, 0, 3)) +>inMultiple : Symbol(C.inMultiple, Decl(a.js, 8, 9), Decl(a.js, 17, 9), Decl(a.js, 26, 9)) + var stringOrNumberOrUndefined = C.inStaticMethod; ->stringOrNumberOrUndefined : Symbol(stringOrNumberOrUndefined, Decl(b.ts, 5, 3), Decl(b.ts, 7, 3), Decl(b.ts, 8, 3), Decl(b.ts, 9, 3), Decl(b.ts, 11, 3), Decl(b.ts, 12, 3), Decl(b.ts, 13, 3)) ->C.inStaticMethod : Symbol(C.inStaticMethod, Decl(a.js, 35, 28), Decl(a.js, 38, 14)) +>stringOrNumberOrUndefined : Symbol(stringOrNumberOrUndefined, Decl(b.ts, 5, 3), Decl(b.ts, 7, 3), Decl(b.ts, 8, 3), Decl(b.ts, 9, 3), Decl(b.ts, 16, 3), Decl(b.ts, 17, 3), Decl(b.ts, 18, 3)) +>C.inStaticMethod : Symbol(C.inStaticMethod, Decl(a.js, 38, 28), Decl(a.js, 41, 14)) >C : Symbol(C, Decl(a.js, 0, 0)) ->inStaticMethod : Symbol(C.inStaticMethod, Decl(a.js, 35, 28), Decl(a.js, 38, 14)) +>inStaticMethod : Symbol(C.inStaticMethod, Decl(a.js, 38, 28), Decl(a.js, 41, 14)) var stringOrNumberOrUndefined = C.inStaticGetter; ->stringOrNumberOrUndefined : Symbol(stringOrNumberOrUndefined, Decl(b.ts, 5, 3), Decl(b.ts, 7, 3), Decl(b.ts, 8, 3), Decl(b.ts, 9, 3), Decl(b.ts, 11, 3), Decl(b.ts, 12, 3), Decl(b.ts, 13, 3)) ->C.inStaticGetter : Symbol(C.inStaticGetter, Decl(a.js, 43, 28), Decl(a.js, 46, 14)) +>stringOrNumberOrUndefined : Symbol(stringOrNumberOrUndefined, Decl(b.ts, 5, 3), Decl(b.ts, 7, 3), Decl(b.ts, 8, 3), Decl(b.ts, 9, 3), Decl(b.ts, 16, 3), Decl(b.ts, 17, 3), Decl(b.ts, 18, 3)) +>C.inStaticGetter : Symbol(C.inStaticGetter, Decl(a.js, 46, 28), Decl(a.js, 49, 14)) >C : Symbol(C, Decl(a.js, 0, 0)) ->inStaticGetter : Symbol(C.inStaticGetter, Decl(a.js, 43, 28), Decl(a.js, 46, 14)) +>inStaticGetter : Symbol(C.inStaticGetter, Decl(a.js, 46, 28), Decl(a.js, 49, 14)) var stringOrNumberOrUndefined = C.inStaticSetter; ->stringOrNumberOrUndefined : Symbol(stringOrNumberOrUndefined, Decl(b.ts, 5, 3), Decl(b.ts, 7, 3), Decl(b.ts, 8, 3), Decl(b.ts, 9, 3), Decl(b.ts, 11, 3), Decl(b.ts, 12, 3), Decl(b.ts, 13, 3)) ->C.inStaticSetter : Symbol(C.inStaticSetter, Decl(a.js, 51, 28), Decl(a.js, 54, 14)) +>stringOrNumberOrUndefined : Symbol(stringOrNumberOrUndefined, Decl(b.ts, 5, 3), Decl(b.ts, 7, 3), Decl(b.ts, 8, 3), Decl(b.ts, 9, 3), Decl(b.ts, 16, 3), Decl(b.ts, 17, 3), Decl(b.ts, 18, 3)) +>C.inStaticSetter : Symbol(C.inStaticSetter, Decl(a.js, 54, 28), Decl(a.js, 57, 14)) >C : Symbol(C, Decl(a.js, 0, 0)) ->inStaticSetter : Symbol(C.inStaticSetter, Decl(a.js, 51, 28), Decl(a.js, 54, 14)) +>inStaticSetter : Symbol(C.inStaticSetter, Decl(a.js, 54, 28), Decl(a.js, 57, 14)) diff --git a/tests/baselines/reference/inferringClassMembersFromAssignments.types b/tests/baselines/reference/inferringClassMembersFromAssignments.types index c1b30ae4519..547cc62ba32 100644 --- a/tests/baselines/reference/inferringClassMembersFromAssignments.types +++ b/tests/baselines/reference/inferringClassMembersFromAssignments.types @@ -25,6 +25,12 @@ class C { >inConstructor : string | number >"string" : "string" } + this.inMultiple = 0; +>this.inMultiple = 0 : 0 +>this.inMultiple : string | number | boolean +>this : this +>inMultiple : string | number | boolean +>0 : 0 } method() { >method : () => void @@ -50,6 +56,12 @@ class C { >inMethod : string | number | undefined >"string" : "string" } + this.inMultiple = "string"; +>this.inMultiple = "string" : "string" +>this.inMultiple : string | number | boolean +>this : this +>inMultiple : string | number | boolean +>"string" : "string" } get() { >get : () => void @@ -75,6 +87,12 @@ class C { >inGetter : string | number | undefined >"string" : "string" } + this.inMultiple = false; +>this.inMultiple = false : false +>this.inMultiple : string | number | boolean +>this : this +>inMultiple : string | number | boolean +>false : false } set() { >set : () => void @@ -214,6 +232,16 @@ var stringOrNumberOrUndefined = c.inSetter; >c : C >inSetter : string | number | undefined +var stringOrNumberOrBoolean: string | number | boolean; +>stringOrNumberOrBoolean : string | number | boolean + +var stringOrNumberOrBoolean = c.inMultiple; +>stringOrNumberOrBoolean : string | number | boolean +>c.inMultiple : string | number | boolean +>c : C +>inMultiple : string | number | boolean + + var stringOrNumberOrUndefined = C.inStaticMethod; >stringOrNumberOrUndefined : string | number | undefined >C.inStaticMethod : string | number | undefined diff --git a/tests/cases/conformance/salsa/inferringClassMembersFromAssignments.ts b/tests/cases/conformance/salsa/inferringClassMembersFromAssignments.ts index dc63f09b3ab..d843e86b725 100644 --- a/tests/cases/conformance/salsa/inferringClassMembersFromAssignments.ts +++ b/tests/cases/conformance/salsa/inferringClassMembersFromAssignments.ts @@ -11,6 +11,7 @@ class C { else { this.inConstructor = "string" } + this.inMultiple = 0; } method() { if (Math.random()) { @@ -19,6 +20,7 @@ class C { else { this.inMethod = "string" } + this.inMultiple = "string"; } get() { if (Math.random()) { @@ -27,6 +29,7 @@ class C { else { this.inGetter = "string" } + this.inMultiple = false; } set() { if (Math.random()) { @@ -74,6 +77,11 @@ var stringOrNumberOrUndefined = c.inMethod; var stringOrNumberOrUndefined = c.inGetter; var stringOrNumberOrUndefined = c.inSetter; +var stringOrNumberOrBoolean: string | number | boolean; + +var stringOrNumberOrBoolean = c.inMultiple; + + var stringOrNumberOrUndefined = C.inStaticMethod; var stringOrNumberOrUndefined = C.inStaticGetter; var stringOrNumberOrUndefined = C.inStaticSetter; From 993397b5ab291567f31bd437c81bc4c24a9d2a3d Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 28 Feb 2017 08:54:38 -0800 Subject: [PATCH 23/65] Introduce CheckMode enum and getContextualMapper() function --- src/compiler/checker.ts | 208 ++++++++++++++++++++-------------------- src/compiler/types.ts | 3 +- 2 files changed, 107 insertions(+), 104 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ff3a1079b18..6e47b7a9808 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -433,6 +433,12 @@ namespace ts { ResolvedReturnType } + const enum CheckMode { + Normal = 0, // Normal type checking + SkipContextSensitive = 1, // Skip context sensitive function expressions + Inferential = 2, // Inferential typing + } + const builtinGlobals = createMap(); builtinGlobals.set(undefinedSymbol.name, undefinedSymbol); @@ -11543,7 +11549,7 @@ namespace ts { while (type) { const thisType = getThisTypeFromContextualType(type); if (thisType) { - return thisType; + return instantiateType(thisType, getContextualMapper(containingLiteral)); } if (literal.parent.kind !== SyntaxKind.PropertyAssignment) { break; @@ -11929,6 +11935,16 @@ namespace ts { return undefined; } + function getContextualMapper(node: Node) { + while (node) { + if (node.contextualMapper) { + return node.contextualMapper; + } + node = node.parent; + } + return identityMapper; + } + // If the given type is an object or union type, if that type has a single signature, and if // that signature is non-generic, return the signature. Otherwise return undefined. function getNonGenericSignature(type: Type, node: FunctionExpression | ArrowFunction | MethodDeclaration): Signature { @@ -12019,31 +12035,12 @@ namespace ts { return result; } - /** - * Detect if the mapper implies an inference context. Specifically, there are 4 possible values - * for a mapper. Let's go through each one of them: - * - * 1. undefined - this means we are not doing inferential typing, but we may do contextual typing, - * which could cause us to assign a parameter a type - * 2. identityMapper - means we want to avoid assigning a parameter a type, whether or not we are in - * inferential typing (context is undefined for the identityMapper) - * 3. a mapper created by createInferenceMapper - we are doing inferential typing, we want to assign - * types to parameters and fix type parameters (context is defined) - * 4. an instantiation mapper created by createTypeMapper or createTypeEraser - this should never be - * passed as the contextual mapper when checking an expression (context is undefined for these) - * - * isInferentialContext is detecting if we are in case 3 - */ - function isInferentialContext(mapper: TypeMapper) { - return mapper && mapper.context; - } - - function checkSpreadExpression(node: SpreadElement, contextualMapper?: TypeMapper): Type { + function checkSpreadExpression(node: SpreadElement, checkMode?: CheckMode): Type { if (languageVersion < ScriptTarget.ES2015 && compilerOptions.downlevelIteration) { checkExternalEmitHelpers(node, ExternalEmitHelpers.SpreadIncludes); } - const arrayOrIterableType = checkExpression(node.expression, contextualMapper); + const arrayOrIterableType = checkExpression(node.expression, checkMode); return checkIteratedTypeOrElementType(arrayOrIterableType, node.expression, /*allowStringInput*/ false, /*allowAsyncIterable*/ false); } @@ -12052,7 +12049,7 @@ namespace ts { (node.kind === SyntaxKind.BinaryExpression && (node).operatorToken.kind === SyntaxKind.EqualsToken); } - function checkArrayLiteral(node: ArrayLiteralExpression, contextualMapper?: TypeMapper): Type { + function checkArrayLiteral(node: ArrayLiteralExpression, checkMode?: CheckMode): Type { const elements = node.elements; let hasSpreadElement = false; const elementTypes: Type[] = []; @@ -12071,7 +12068,7 @@ namespace ts { // get the contextual element type from it. So we do something similar to // getContextualTypeForElementExpression, which will crucially not error // if there is no index type / iterated type. - const restArrayType = checkExpression((e).expression, contextualMapper); + const restArrayType = checkExpression((e).expression, checkMode); const restElementType = getIndexTypeOfType(restArrayType, IndexKind.Number) || getIteratedTypeOrElementType(restArrayType, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterable*/ false, /*checkAssignability*/ false); if (restElementType) { @@ -12079,7 +12076,7 @@ namespace ts { } } else { - const type = checkExpressionForMutableLocation(e, contextualMapper); + const type = checkExpressionForMutableLocation(e, checkMode); elementTypes.push(type); } hasSpreadElement = hasSpreadElement || e.kind === SyntaxKind.SpreadElement; @@ -12194,7 +12191,7 @@ namespace ts { return createIndexInfo(unionType, /*isReadonly*/ false); } - function checkObjectLiteral(node: ObjectLiteralExpression, contextualMapper?: TypeMapper): Type { + function checkObjectLiteral(node: ObjectLiteralExpression, checkMode?: CheckMode): Type { const inDestructuringPattern = isAssignmentTarget(node); // Grammar checking checkGrammarObjectLiteralExpression(node, inDestructuringPattern); @@ -12221,14 +12218,14 @@ namespace ts { isObjectLiteralMethod(memberDecl)) { let type: Type; if (memberDecl.kind === SyntaxKind.PropertyAssignment) { - type = checkPropertyAssignment(memberDecl, contextualMapper); + type = checkPropertyAssignment(memberDecl, checkMode); } else if (memberDecl.kind === SyntaxKind.MethodDeclaration) { - type = checkObjectLiteralMethod(memberDecl, contextualMapper); + type = checkObjectLiteralMethod(memberDecl, checkMode); } else { Debug.assert(memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment); - type = checkExpressionForMutableLocation((memberDecl).name, contextualMapper); + type = checkExpressionForMutableLocation((memberDecl).name, checkMode); } typeFlags |= type.flags; @@ -12434,7 +12431,7 @@ namespace ts { * @remarks Because this function calls getSpreadType, it needs to use the same checks as checkObjectLiteral, * which also calls getSpreadType. */ - function createJsxAttributesTypeFromAttributesProperty(openingLikeElement: JsxOpeningLikeElement, filter?: (symbol: Symbol) => boolean, contextualMapper?: TypeMapper) { + function createJsxAttributesTypeFromAttributesProperty(openingLikeElement: JsxOpeningLikeElement, filter?: (symbol: Symbol) => boolean, checkMode?: CheckMode) { const attributes = openingLikeElement.attributes; let attributesTable = createMap(); let spread: Type = emptyObjectType; @@ -12443,7 +12440,7 @@ namespace ts { const member = attributeDecl.symbol; if (isJsxAttribute(attributeDecl)) { const exprType = attributeDecl.initializer ? - checkExpression(attributeDecl.initializer, contextualMapper) : + checkExpression(attributeDecl.initializer, checkMode) : trueType; // is sugar for const attributeSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient | member.flags, member.name); @@ -12514,8 +12511,8 @@ namespace ts { * (See "checkApplicableSignatureForJsxOpeningLikeElement" for how the function is used) * @param node a JSXAttributes to be resolved of its type */ - function checkJsxAttributes(node: JsxAttributes, contextualMapper?: TypeMapper) { - return createJsxAttributesTypeFromAttributesProperty(node.parent as JsxOpeningLikeElement, /*filter*/ undefined, contextualMapper); + function checkJsxAttributes(node: JsxAttributes, checkMode?: CheckMode) { + return createJsxAttributesTypeFromAttributesProperty(node.parent as JsxOpeningLikeElement, /*filter*/ undefined, checkMode); } function getJsxType(name: string) { @@ -13013,9 +13010,9 @@ namespace ts { } } - function checkJsxExpression(node: JsxExpression, contextualMapper?: TypeMapper) { + function checkJsxExpression(node: JsxExpression, checkMode?: CheckMode) { if (node.expression) { - const type = checkExpression(node.expression, contextualMapper); + const type = checkExpression(node.expression, checkMode); if (node.dotDotDotToken && type !== anyType && !isArrayType(type)) { error(node, Diagnostics.JSX_spread_child_must_be_an_array_type, node.toString(), typeToString(type)); } @@ -14877,9 +14874,9 @@ namespace ts { return signature.parameters.length > 0 ? getTypeAtPosition(signature, 0) : neverType; } - function assignContextualParameterTypes(signature: Signature, context: Signature, mapper: TypeMapper) { + function assignContextualParameterTypes(signature: Signature, context: Signature, mapper: TypeMapper, checkMode: CheckMode) { const len = signature.parameters.length - (signature.hasRestParameter ? 1 : 0); - if (isInferentialContext(mapper)) { + if (checkMode === CheckMode.Inferential) { for (let i = 0; i < len; i++) { const declaration = signature.parameters[i].valueDeclaration; if (declaration.type) { @@ -14893,21 +14890,21 @@ namespace ts { if (!parameter) { signature.thisParameter = createSymbolWithType(context.thisParameter, undefined); } - assignTypeToParameterAndFixTypeParameters(signature.thisParameter, getTypeOfSymbol(context.thisParameter), mapper); + assignTypeToParameterAndFixTypeParameters(signature.thisParameter, getTypeOfSymbol(context.thisParameter), mapper, checkMode); } } for (let i = 0; i < len; i++) { const parameter = signature.parameters[i]; if (!(parameter.valueDeclaration).type) { const contextualParameterType = getTypeAtPosition(context, i); - assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper); + assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper, checkMode); } } if (signature.hasRestParameter && isRestParameterIndex(context, signature.parameters.length - 1)) { const parameter = lastOrUndefined(signature.parameters); if (!(parameter.valueDeclaration).type) { const contextualParameterType = getTypeOfSymbol(lastOrUndefined(context.parameters)); - assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper); + assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper, checkMode); } } } @@ -14927,7 +14924,7 @@ namespace ts { } } - function assignTypeToParameterAndFixTypeParameters(parameter: Symbol, contextualType: Type, mapper: TypeMapper) { + function assignTypeToParameterAndFixTypeParameters(parameter: Symbol, contextualType: Type, mapper: TypeMapper, checkMode: CheckMode) { const links = getSymbolLinks(parameter); if (!links.type) { links.type = instantiateType(contextualType, mapper); @@ -14939,7 +14936,7 @@ namespace ts { } assignBindingElementTypes(parameter.valueDeclaration); } - else if (isInferentialContext(mapper)) { + else if (checkMode === CheckMode.Inferential) { // Even if the parameter already has a type, it might be because it was given a type while // processing the function as an argument to a prior signature during overload resolution. // If this was the case, it may have caused some type parameters to be fixed. So here, @@ -15007,7 +15004,7 @@ namespace ts { return promiseType; } - function getReturnTypeFromBody(func: FunctionLikeDeclaration, contextualMapper?: TypeMapper): Type { + function getReturnTypeFromBody(func: FunctionLikeDeclaration, checkMode?: CheckMode): Type { const contextualSignature = getContextualSignatureForFunctionLikeDeclaration(func); if (!func.body) { return unknownType; @@ -15016,7 +15013,7 @@ namespace ts { const functionFlags = getFunctionFlags(func); let type: Type; if (func.body.kind !== SyntaxKind.Block) { - type = checkExpressionCached(func.body, contextualMapper); + type = checkExpressionCached(func.body, checkMode); if (functionFlags & FunctionFlags.Async) { // From within an async function you can return either a non-promise value or a promise. Any // Promise/A+ compatible implementation will always assimilate any foreign promise, so the @@ -15028,7 +15025,7 @@ namespace ts { else { let types: Type[]; if (functionFlags & FunctionFlags.Generator) { // Generator or AsyncGenerator function - types = checkAndAggregateYieldOperandTypes(func, contextualMapper); + types = checkAndAggregateYieldOperandTypes(func, checkMode); if (types.length === 0) { const iterableIteratorAny = functionFlags & FunctionFlags.Async ? createAsyncIterableIteratorType(anyType) // AsyncGenerator function @@ -15041,7 +15038,7 @@ namespace ts { } } else { - types = checkAndAggregateReturnExpressionTypes(func, contextualMapper); + types = checkAndAggregateReturnExpressionTypes(func, checkMode); if (!types) { // For an async function, the return type will not be never, but rather a Promise for never. return functionFlags & FunctionFlags.Async @@ -15085,13 +15082,13 @@ namespace ts { : widenedType; // Generator function, AsyncGenerator function, or normal function } - function checkAndAggregateYieldOperandTypes(func: FunctionLikeDeclaration, contextualMapper: TypeMapper): Type[] { + function checkAndAggregateYieldOperandTypes(func: FunctionLikeDeclaration, checkMode: CheckMode): Type[] { const aggregatedTypes: Type[] = []; const functionFlags = getFunctionFlags(func); forEachYieldExpression(func.body, yieldExpression => { const expr = yieldExpression.expression; if (expr) { - let type = checkExpressionCached(expr, contextualMapper); + let type = checkExpressionCached(expr, checkMode); if (yieldExpression.asteriskToken) { // A yield* expression effectively yields everything that its operand yields type = checkIteratedTypeOrElementType(type, yieldExpression.expression, /*allowStringInput*/ false, (functionFlags & FunctionFlags.Async) !== 0); @@ -15131,7 +15128,7 @@ namespace ts { return true; } - function checkAndAggregateReturnExpressionTypes(func: FunctionLikeDeclaration, contextualMapper: TypeMapper): Type[] { + function checkAndAggregateReturnExpressionTypes(func: FunctionLikeDeclaration, checkMode: CheckMode): Type[] { const functionFlags = getFunctionFlags(func); const aggregatedTypes: Type[] = []; let hasReturnWithNoExpression = functionHasImplicitReturn(func); @@ -15139,7 +15136,7 @@ namespace ts { forEachReturnStatement(func.body, returnStatement => { const expr = returnStatement.expression; if (expr) { - let type = checkExpressionCached(expr, contextualMapper); + let type = checkExpressionCached(expr, checkMode); if (functionFlags & FunctionFlags.Async) { // From within an async function you can return either a non-promise value or a promise. Any // Promise/A+ compatible implementation will always assimilate any foreign promise, so the @@ -15226,7 +15223,7 @@ namespace ts { } } - function checkFunctionExpressionOrObjectLiteralMethod(node: FunctionExpression | MethodDeclaration, contextualMapper?: TypeMapper): Type { + function checkFunctionExpressionOrObjectLiteralMethod(node: FunctionExpression | MethodDeclaration, checkMode?: CheckMode): Type { Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node)); // Grammar checking @@ -15236,7 +15233,7 @@ namespace ts { } // The identityMapper object is used to indicate that function expressions are wildcards - if (contextualMapper === identityMapper && isContextSensitive(node)) { + if (checkMode === CheckMode.SkipContextSensitive && isContextSensitive(node)) { checkNodeDeferred(node); return anyFunctionType; } @@ -15244,7 +15241,7 @@ namespace ts { const links = getNodeLinks(node); const type = getTypeOfSymbol(node.symbol); const contextSensitive = isContextSensitive(node); - const mightFixTypeParameters = contextSensitive && isInferentialContext(contextualMapper); + const mightFixTypeParameters = contextSensitive && checkMode === CheckMode.Inferential; // Check if function expression is contextually typed and assign parameter types if so. // See the comment in assignTypeToParameterAndFixTypeParameters to understand why we need to @@ -15260,10 +15257,10 @@ namespace ts { if (contextualSignature) { const signature = getSignaturesOfType(type, SignatureKind.Call)[0]; if (contextSensitive) { - assignContextualParameterTypes(signature, contextualSignature, contextualMapper || identityMapper); + assignContextualParameterTypes(signature, contextualSignature, getContextualMapper(node), checkMode); } if (mightFixTypeParameters || !node.type && !signature.resolvedReturnType) { - const returnType = getReturnTypeFromBody(node, contextualMapper); + const returnType = getReturnTypeFromBody(node, checkMode); if (!signature.resolvedReturnType) { signature.resolvedReturnType = returnType; } @@ -15639,7 +15636,7 @@ namespace ts { } } - function checkArrayLiteralAssignment(node: ArrayLiteralExpression, sourceType: Type, contextualMapper?: TypeMapper): Type { + function checkArrayLiteralAssignment(node: ArrayLiteralExpression, sourceType: Type, checkMode?: CheckMode): Type { if (languageVersion < ScriptTarget.ES2015 && compilerOptions.downlevelIteration) { checkExternalEmitHelpers(node, ExternalEmitHelpers.Read); } @@ -15650,13 +15647,13 @@ namespace ts { const elementType = checkIteratedTypeOrElementType(sourceType, node, /*allowStringInput*/ false, /*allowAsyncIterable*/ false) || unknownType; const elements = node.elements; for (let i = 0; i < elements.length; i++) { - checkArrayLiteralDestructuringElementAssignment(node, sourceType, i, elementType, contextualMapper); + checkArrayLiteralDestructuringElementAssignment(node, sourceType, i, elementType, checkMode); } return sourceType; } function checkArrayLiteralDestructuringElementAssignment(node: ArrayLiteralExpression, sourceType: Type, - elementIndex: number, elementType: Type, contextualMapper?: TypeMapper) { + elementIndex: number, elementType: Type, checkMode?: CheckMode) { const elements = node.elements; const element = elements[elementIndex]; if (element.kind !== SyntaxKind.OmittedExpression) { @@ -15668,7 +15665,7 @@ namespace ts { ? getTypeOfPropertyOfType(sourceType, propName) : elementType; if (type) { - return checkDestructuringAssignment(element, type, contextualMapper); + return checkDestructuringAssignment(element, type, checkMode); } else { // We still need to check element expression here because we may need to set appropriate flag on the expression @@ -15692,7 +15689,7 @@ namespace ts { error((restExpression).operatorToken, Diagnostics.A_rest_element_cannot_have_an_initializer); } else { - return checkDestructuringAssignment(restExpression, createArrayType(elementType), contextualMapper); + return checkDestructuringAssignment(restExpression, createArrayType(elementType), checkMode); } } } @@ -15700,7 +15697,7 @@ namespace ts { return undefined; } - function checkDestructuringAssignment(exprOrAssignment: Expression | ShorthandPropertyAssignment, sourceType: Type, contextualMapper?: TypeMapper): Type { + function checkDestructuringAssignment(exprOrAssignment: Expression | ShorthandPropertyAssignment, sourceType: Type, checkMode?: CheckMode): Type { let target: Expression; if (exprOrAssignment.kind === SyntaxKind.ShorthandPropertyAssignment) { const prop = exprOrAssignment; @@ -15711,7 +15708,7 @@ namespace ts { !(getFalsyFlags(checkExpression(prop.objectAssignmentInitializer)) & TypeFlags.Undefined)) { sourceType = getTypeWithFacts(sourceType, TypeFacts.NEUndefined); } - checkBinaryLikeExpression(prop.name, prop.equalsToken, prop.objectAssignmentInitializer, contextualMapper); + checkBinaryLikeExpression(prop.name, prop.equalsToken, prop.objectAssignmentInitializer, checkMode); } target = (exprOrAssignment).name; } @@ -15720,20 +15717,20 @@ namespace ts { } if (target.kind === SyntaxKind.BinaryExpression && (target).operatorToken.kind === SyntaxKind.EqualsToken) { - checkBinaryExpression(target, contextualMapper); + checkBinaryExpression(target, checkMode); target = (target).left; } if (target.kind === SyntaxKind.ObjectLiteralExpression) { return checkObjectLiteralAssignment(target, sourceType); } if (target.kind === SyntaxKind.ArrayLiteralExpression) { - return checkArrayLiteralAssignment(target, sourceType, contextualMapper); + return checkArrayLiteralAssignment(target, sourceType, checkMode); } - return checkReferenceAssignment(target, sourceType, contextualMapper); + return checkReferenceAssignment(target, sourceType, checkMode); } - function checkReferenceAssignment(target: Expression, sourceType: Type, contextualMapper?: TypeMapper): Type { - const targetType = checkExpression(target, contextualMapper); + function checkReferenceAssignment(target: Expression, sourceType: Type, checkMode?: CheckMode): Type { + const targetType = checkExpression(target, checkMode); const error = target.parent.kind === SyntaxKind.SpreadAssignment ? Diagnostics.The_target_of_an_object_rest_assignment_must_be_a_variable_or_a_property_access : Diagnostics.The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access; @@ -15821,17 +15818,17 @@ namespace ts { getUnionType([type1, type2], /*subtypeReduction*/ true); } - function checkBinaryExpression(node: BinaryExpression, contextualMapper?: TypeMapper) { - return checkBinaryLikeExpression(node.left, node.operatorToken, node.right, contextualMapper, node); + function checkBinaryExpression(node: BinaryExpression, checkMode?: CheckMode) { + return checkBinaryLikeExpression(node.left, node.operatorToken, node.right, checkMode, node); } - function checkBinaryLikeExpression(left: Expression, operatorToken: Node, right: Expression, contextualMapper?: TypeMapper, errorNode?: Node) { + function checkBinaryLikeExpression(left: Expression, operatorToken: Node, right: Expression, checkMode?: CheckMode, errorNode?: Node) { const operator = operatorToken.kind; if (operator === SyntaxKind.EqualsToken && (left.kind === SyntaxKind.ObjectLiteralExpression || left.kind === SyntaxKind.ArrayLiteralExpression)) { - return checkDestructuringAssignment(left, checkExpression(right, contextualMapper), contextualMapper); + return checkDestructuringAssignment(left, checkExpression(right, checkMode), checkMode); } - let leftType = checkExpression(left, contextualMapper); - let rightType = checkExpression(right, contextualMapper); + let leftType = checkExpression(left, checkMode); + let rightType = checkExpression(right, checkMode); switch (operator) { case SyntaxKind.AsteriskToken: case SyntaxKind.AsteriskAsteriskToken: @@ -16094,10 +16091,10 @@ namespace ts { return anyType; } - function checkConditionalExpression(node: ConditionalExpression, contextualMapper?: TypeMapper): Type { + function checkConditionalExpression(node: ConditionalExpression, checkMode?: CheckMode): Type { checkExpression(node.condition); - const type1 = checkExpression(node.whenTrue, contextualMapper); - const type2 = checkExpression(node.whenFalse, contextualMapper); + const type1 = checkExpression(node.whenTrue, checkMode); + const type2 = checkExpression(node.whenFalse, checkMode); return getBestChoiceType(type1, type2); } @@ -16130,15 +16127,20 @@ namespace ts { return stringType; } - function checkExpressionWithContextualType(node: Expression, contextualType: Type, contextualMapper?: TypeMapper): Type { + function checkExpressionWithContextualType(node: Expression, contextualType: Type, contextualMapper: TypeMapper): Type { const saveContextualType = node.contextualType; + const saveContextualMapper = node.contextualMapper; node.contextualType = contextualType; - const result = checkExpression(node, contextualMapper); + node.contextualMapper = contextualMapper; + const checkMode = contextualMapper === identityMapper ? CheckMode.SkipContextSensitive : + contextualMapper ? CheckMode.Inferential : CheckMode.Normal; + const result = checkExpression(node, checkMode); node.contextualType = saveContextualType; + node.contextualMapper = saveContextualMapper; return result; } - function checkExpressionCached(node: Expression, contextualMapper?: TypeMapper): Type { + function checkExpressionCached(node: Expression, checkMode?: CheckMode): Type { const links = getNodeLinks(node); if (!links.resolvedType) { // When computing a type that we're going to cache, we need to ignore any ongoing control flow @@ -16146,7 +16148,7 @@ namespace ts { // to the top of the stack ensures all transient types are computed from a known point. const saveFlowLoopStart = flowLoopStart; flowLoopStart = flowLoopCount; - links.resolvedType = checkExpression(node, contextualMapper); + links.resolvedType = checkExpression(node, checkMode); flowLoopStart = saveFlowLoopStart; } return links.resolvedType; @@ -16181,12 +16183,12 @@ namespace ts { return false; } - function checkExpressionForMutableLocation(node: Expression, contextualMapper?: TypeMapper): Type { - const type = checkExpression(node, contextualMapper); + function checkExpressionForMutableLocation(node: Expression, checkMode?: CheckMode): Type { + const type = checkExpression(node, checkMode); return isTypeAssertion(node) || isLiteralContextualType(getContextualType(node)) ? type : getWidenedLiteralType(type); } - function checkPropertyAssignment(node: PropertyAssignment, contextualMapper?: TypeMapper): Type { + function checkPropertyAssignment(node: PropertyAssignment, checkMode?: CheckMode): Type { // Do not use hasDynamicName here, because that returns false for well known symbols. // We want to perform checkComputedPropertyName for all computed properties, including // well known symbols. @@ -16194,10 +16196,10 @@ namespace ts { checkComputedPropertyName(node.name); } - return checkExpressionForMutableLocation((node).initializer, contextualMapper); + return checkExpressionForMutableLocation((node).initializer, checkMode); } - function checkObjectLiteralMethod(node: MethodDeclaration, contextualMapper?: TypeMapper): Type { + function checkObjectLiteralMethod(node: MethodDeclaration, checkMode?: CheckMode): Type { // Grammar checking checkGrammarMethod(node); @@ -16208,19 +16210,19 @@ namespace ts { checkComputedPropertyName(node.name); } - const uninstantiatedType = checkFunctionExpressionOrObjectLiteralMethod(node, contextualMapper); - return instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, contextualMapper); + const uninstantiatedType = checkFunctionExpressionOrObjectLiteralMethod(node, checkMode); + return instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, checkMode); } - function instantiateTypeWithSingleGenericCallSignature(node: Expression | MethodDeclaration, type: Type, contextualMapper?: TypeMapper) { - if (isInferentialContext(contextualMapper)) { + function instantiateTypeWithSingleGenericCallSignature(node: Expression | MethodDeclaration, type: Type, checkMode?: CheckMode) { + if (checkMode === CheckMode.Inferential) { const signature = getSingleCallSignature(type); if (signature && signature.typeParameters) { const contextualType = getApparentTypeOfContextualType(node); if (contextualType) { const contextualSignature = getSingleCallSignature(contextualType); if (contextualSignature && !contextualSignature.typeParameters) { - return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, contextualMapper)); + return getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, getContextualMapper(node))); } } } @@ -16254,14 +16256,14 @@ namespace ts { // object, it serves as an indicator that all contained function and arrow expressions should be considered to // have the wildcard function type; this form of type check is used during overload resolution to exclude // contextually typed function and arrow expressions in the initial phase. - function checkExpression(node: Expression | QualifiedName, contextualMapper?: TypeMapper): Type { + function checkExpression(node: Expression | QualifiedName, checkMode?: CheckMode): Type { let type: Type; if (node.kind === SyntaxKind.QualifiedName) { type = checkQualifiedName(node); } else { - const uninstantiatedType = checkExpressionWorker(node, contextualMapper); - type = instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, contextualMapper); + const uninstantiatedType = checkExpressionWorker(node, checkMode); + type = instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, checkMode); } if (isConstEnumObjectType(type)) { @@ -16281,7 +16283,7 @@ namespace ts { return type; } - function checkExpressionWorker(node: Expression, contextualMapper: TypeMapper): Type { + function checkExpressionWorker(node: Expression, checkMode: CheckMode): Type { switch (node.kind) { case SyntaxKind.Identifier: return checkIdentifier(node); @@ -16303,9 +16305,9 @@ namespace ts { case SyntaxKind.RegularExpressionLiteral: return globalRegExpType; case SyntaxKind.ArrayLiteralExpression: - return checkArrayLiteral(node, contextualMapper); + return checkArrayLiteral(node, checkMode); case SyntaxKind.ObjectLiteralExpression: - return checkObjectLiteral(node, contextualMapper); + return checkObjectLiteral(node, checkMode); case SyntaxKind.PropertyAccessExpression: return checkPropertyAccessExpression(node); case SyntaxKind.ElementAccessExpression: @@ -16316,12 +16318,12 @@ namespace ts { case SyntaxKind.TaggedTemplateExpression: return checkTaggedTemplateExpression(node); case SyntaxKind.ParenthesizedExpression: - return checkExpression((node).expression, contextualMapper); + return checkExpression((node).expression, checkMode); case SyntaxKind.ClassExpression: return checkClassExpression(node); case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: - return checkFunctionExpressionOrObjectLiteralMethod(node, contextualMapper); + return checkFunctionExpressionOrObjectLiteralMethod(node, checkMode); case SyntaxKind.TypeOfExpression: return checkTypeOfExpression(node); case SyntaxKind.TypeAssertionExpression: @@ -16342,23 +16344,23 @@ namespace ts { case SyntaxKind.PostfixUnaryExpression: return checkPostfixUnaryExpression(node); case SyntaxKind.BinaryExpression: - return checkBinaryExpression(node, contextualMapper); + return checkBinaryExpression(node, checkMode); case SyntaxKind.ConditionalExpression: - return checkConditionalExpression(node, contextualMapper); + return checkConditionalExpression(node, checkMode); case SyntaxKind.SpreadElement: - return checkSpreadExpression(node, contextualMapper); + return checkSpreadExpression(node, checkMode); case SyntaxKind.OmittedExpression: return undefinedWideningType; case SyntaxKind.YieldExpression: return checkYieldExpression(node); case SyntaxKind.JsxExpression: - return checkJsxExpression(node, contextualMapper); + return checkJsxExpression(node, checkMode); case SyntaxKind.JsxElement: return checkJsxElement(node); case SyntaxKind.JsxSelfClosingElement: return checkJsxSelfClosingElement(node); case SyntaxKind.JsxAttributes: - return checkJsxAttributes(node, contextualMapper); + return checkJsxAttributes(node, checkMode); case SyntaxKind.JsxOpeningElement: Debug.fail("Shouldn't ever directly check a JsxOpeningElement"); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index de42d5d9745..d42be483755 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -522,6 +522,8 @@ /* @internal */ localSymbol?: Symbol; // Local symbol declared by node (initialized by binding only for exported nodes) /* @internal */ flowNode?: FlowNode; // Associated FlowNode (initialized by binding) /* @internal */ emitNode?: EmitNode; // Associated EmitNode (initialized by transforms) + /* @internal */ contextualType?: Type; // Used to temporarily assign a contextual type during overload resolution + /* @internal */ contextualMapper?: TypeMapper; // Mapper for contextual type } export interface NodeArray extends Array, TextRange { @@ -960,7 +962,6 @@ export interface Expression extends Node { _expressionBrand: any; - contextualType?: Type; // Used to temporarily assign a contextual type during overload resolution } export interface OmittedExpression extends Expression { From ff2cfd2af5008e086470ac244442559a6febbb2e Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 28 Feb 2017 09:49:54 -0800 Subject: [PATCH 24/65] Update test --- .../thisType/thisTypeInObjectLiterals2.ts | 59 ++++++++++++++++++- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals2.ts b/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals2.ts index 7358b47259c..d476679aef1 100644 --- a/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals2.ts +++ b/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals2.ts @@ -1,4 +1,5 @@ // @declaration: true +// @strictNullChecks: true // @noImplicitAny: true // @noImplicitThis: true // @target: es5 @@ -34,15 +35,19 @@ let obj1 = { type Point = { x: number; y: number; - moveBy(dx: number, dy: number): void; + z?: number; + moveBy(dx: number, dy: number, dz?: number): void; } let p1: Point = { x: 10, y: 20, - moveBy(dx, dy) { + moveBy(dx, dy, dz) { this.x += dx; this.y += dy; + if (this.z && dz) { + this.z += dz; + } } }; @@ -51,9 +56,12 @@ declare function f1(p: Point): void; f1({ x: 10, y: 20, - moveBy(dx, dy) { + moveBy(dx, dy, dz) { this.x += dx; this.y += dy; + if (this.z && dz) { + this.z += dz; + } } }); @@ -97,6 +105,51 @@ let x2 = makeObject2({ } }); +// Check pattern similar to Object.defineProperty and Object.defineProperties + +type PropDesc = { + value?: T; + get?(): T; + set?(value: T): void; +} + +type PropDescMap = { + [K in keyof T]: PropDesc; +} + +declare function defineProp(obj: T, name: K, desc: PropDesc & ThisType): T & Record; + +declare function defineProps(obj: T, descs: PropDescMap & ThisType): T & U; + +let p10 = defineProp(p1, "foo", { value: 42 }); +p10.foo = p10.foo + 1; + +let p11 = defineProp(p1, "bar", { + get() { + return this.x; + }, + set(value: number) { + this.x = value; + } +}); +p11.bar = p11.bar + 1; + +let p12 = defineProps(p1, { + foo: { + value: 42 + }, + bar: { + get(): number { + return this.x; + }, + set(value: number) { + this.x = value; + } + } +}); +p12.foo = p12.foo + 1; +p12.bar = p12.bar + 1; + // Proof of concept for typing of Vue.js type Accessors = { [K in keyof T]: (() => T[K]) | Computed }; From c87c124831856bd912d851a0505bd706e39022cb Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 28 Feb 2017 09:50:02 -0800 Subject: [PATCH 25/65] Accept new baselines --- .../reference/thisTypeInObjectLiterals2.js | 113 +++- .../thisTypeInObjectLiterals2.symbols | 532 ++++++++++++------ .../reference/thisTypeInObjectLiterals2.types | 262 ++++++++- 3 files changed, 715 insertions(+), 192 deletions(-) diff --git a/tests/baselines/reference/thisTypeInObjectLiterals2.js b/tests/baselines/reference/thisTypeInObjectLiterals2.js index 08f02b6c5af..88cbd2555f6 100644 --- a/tests/baselines/reference/thisTypeInObjectLiterals2.js +++ b/tests/baselines/reference/thisTypeInObjectLiterals2.js @@ -31,15 +31,19 @@ let obj1 = { type Point = { x: number; y: number; - moveBy(dx: number, dy: number): void; + z?: number; + moveBy(dx: number, dy: number, dz?: number): void; } let p1: Point = { x: 10, y: 20, - moveBy(dx, dy) { + moveBy(dx, dy, dz) { this.x += dx; this.y += dy; + if (this.z && dz) { + this.z += dz; + } } }; @@ -48,9 +52,12 @@ declare function f1(p: Point): void; f1({ x: 10, y: 20, - moveBy(dx, dy) { + moveBy(dx, dy, dz) { this.x += dx; this.y += dy; + if (this.z && dz) { + this.z += dz; + } } }); @@ -94,6 +101,51 @@ let x2 = makeObject2({ } }); +// Check pattern similar to Object.defineProperty and Object.defineProperties + +type PropDesc = { + value?: T; + get?(): T; + set?(value: T): void; +} + +type PropDescMap = { + [K in keyof T]: PropDesc; +} + +declare function defineProp(obj: T, name: K, desc: PropDesc & ThisType): T & Record; + +declare function defineProps(obj: T, descs: PropDescMap & ThisType): T & U; + +let p10 = defineProp(p1, "foo", { value: 42 }); +p10.foo = p10.foo + 1; + +let p11 = defineProp(p1, "bar", { + get() { + return this.x; + }, + set(value: number) { + this.x = value; + } +}); +p11.bar = p11.bar + 1; + +let p12 = defineProps(p1, { + foo: { + value: 42 + }, + bar: { + get(): number { + return this.x; + }, + set(value: number) { + this.x = value; + } + } +}); +p12.foo = p12.foo + 1; +p12.bar = p12.bar + 1; + // Proof of concept for typing of Vue.js type Accessors = { [K in keyof T]: (() => T[K]) | Computed }; @@ -168,17 +220,23 @@ var obj1 = { var p1 = { x: 10, y: 20, - moveBy: function (dx, dy) { + moveBy: function (dx, dy, dz) { this.x += dx; this.y += dy; + if (this.z && dz) { + this.z += dz; + } } }; f1({ x: 10, y: 20, - moveBy: function (dx, dy) { + moveBy: function (dx, dy, dz) { this.x += dx; this.y += dy; + if (this.z && dz) { + this.z += dz; + } } }); var x1 = makeObject({ @@ -199,6 +257,32 @@ var x2 = makeObject2({ } } }); +var p10 = defineProp(p1, "foo", { value: 42 }); +p10.foo = p10.foo + 1; +var p11 = defineProp(p1, "bar", { + get: function () { + return this.x; + }, + set: function (value) { + this.x = value; + } +}); +p11.bar = p11.bar + 1; +var p12 = defineProps(p1, { + foo: { + value: 42 + }, + bar: { + get: function () { + return this.x; + }, + set: function (value) { + this.x = value; + } + } +}); +p12.foo = p12.foo + 1; +p12.bar = p12.bar + 1; var vue = new Vue({ data: function () { return ({ x: 1, y: 2 }); }, methods: { @@ -240,7 +324,8 @@ declare let obj1: { declare type Point = { x: number; y: number; - moveBy(dx: number, dy: number): void; + z?: number; + moveBy(dx: number, dy: number, dz?: number): void; }; declare let p1: Point; declare function f1(p: Point): void; @@ -266,6 +351,22 @@ declare let x2: { } & { moveBy(dx: number, dy: number): void; }; +declare type PropDesc = { + value?: T; + get?(): T; + set?(value: T): void; +}; +declare type PropDescMap = { + [K in keyof T]: PropDesc; +}; +declare function defineProp(obj: T, name: K, desc: PropDesc & ThisType): T & Record; +declare function defineProps(obj: T, descs: PropDescMap & ThisType): T & U; +declare let p10: Point & Record<"foo", number>; +declare let p11: Point & Record<"bar", number>; +declare let p12: Point & { + foo: number; + bar: number; +}; declare type Accessors = { [K in keyof T]: (() => T[K]) | Computed; }; diff --git a/tests/baselines/reference/thisTypeInObjectLiterals2.symbols b/tests/baselines/reference/thisTypeInObjectLiterals2.symbols index ef72c320cce..e7412ab487f 100644 --- a/tests/baselines/reference/thisTypeInObjectLiterals2.symbols +++ b/tests/baselines/reference/thisTypeInObjectLiterals2.symbols @@ -75,71 +75,103 @@ type Point = { y: number; >y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14)) - moveBy(dx: number, dy: number): void; ->moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) ->dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 32, 11)) ->dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 32, 22)) + z?: number; +>z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) + + moveBy(dx: number, dy: number, dz?: number): void; +>moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 32, 15)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 33, 11)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 33, 22)) +>dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 33, 34)) } let p1: Point = { ->p1 : Symbol(p1, Decl(thisTypeInObjectLiterals2.ts, 35, 3)) +>p1 : Symbol(p1, Decl(thisTypeInObjectLiterals2.ts, 36, 3)) >Point : Symbol(Point, Decl(thisTypeInObjectLiterals2.ts, 24, 2)) x: 10, ->x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 35, 17)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 36, 17)) y: 20, ->y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 36, 10)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 37, 10)) - moveBy(dx, dy) { ->moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 37, 10)) ->dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 38, 11)) ->dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 38, 14)) + moveBy(dx, dy, dz) { +>moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 38, 10)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 39, 11)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 39, 14)) +>dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 39, 18)) this.x += dx; >this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) >this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) >x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) ->dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 38, 11)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 39, 11)) this.y += dy; >this.y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14)) >this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) >y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14)) ->dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 38, 14)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 39, 14)) + + if (this.z && dz) { +>this.z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) +>dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 39, 18)) + + this.z += dz; +>this.z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) +>dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 39, 18)) + } } }; declare function f1(p: Point): void; ->f1 : Symbol(f1, Decl(thisTypeInObjectLiterals2.ts, 42, 2)) ->p : Symbol(p, Decl(thisTypeInObjectLiterals2.ts, 44, 20)) +>f1 : Symbol(f1, Decl(thisTypeInObjectLiterals2.ts, 46, 2)) +>p : Symbol(p, Decl(thisTypeInObjectLiterals2.ts, 48, 20)) >Point : Symbol(Point, Decl(thisTypeInObjectLiterals2.ts, 24, 2)) f1({ ->f1 : Symbol(f1, Decl(thisTypeInObjectLiterals2.ts, 42, 2)) +>f1 : Symbol(f1, Decl(thisTypeInObjectLiterals2.ts, 46, 2)) x: 10, ->x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 46, 4)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 50, 4)) y: 20, ->y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 47, 10)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 51, 10)) - moveBy(dx, dy) { ->moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 48, 10)) ->dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 49, 11)) ->dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 49, 14)) + moveBy(dx, dy, dz) { +>moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 52, 10)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 53, 11)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 53, 14)) +>dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 53, 18)) this.x += dx; >this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) >this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) >x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) ->dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 49, 11)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 53, 11)) this.y += dy; >this.y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14)) >this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) >y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14)) ->dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 49, 14)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 53, 14)) + + if (this.z && dz) { +>this.z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) +>dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 53, 18)) + + this.z += dz; +>this.z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) +>dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 53, 18)) + } } }); @@ -147,59 +179,59 @@ f1({ // ThisType, 'this' is of type T. type ObjectDescriptor = { ->ObjectDescriptor : Symbol(ObjectDescriptor, Decl(thisTypeInObjectLiterals2.ts, 53, 3)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 58, 22)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 58, 24)) +>ObjectDescriptor : Symbol(ObjectDescriptor, Decl(thisTypeInObjectLiterals2.ts, 60, 3)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 65, 22)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 65, 24)) data?: D; ->data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 58, 31)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 58, 22)) +>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 65, 31)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 65, 22)) methods?: M & ThisType; // Type of 'this' in methods is D & M ->methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 59, 13)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 58, 24)) +>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 66, 13)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 65, 24)) >ThisType : Symbol(ThisType, Decl(lib.d.ts, --, --)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 58, 22)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 58, 24)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 65, 22)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 65, 24)) } declare function makeObject(desc: ObjectDescriptor): D & M; ->makeObject : Symbol(makeObject, Decl(thisTypeInObjectLiterals2.ts, 61, 1)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 63, 28)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 63, 30)) ->desc : Symbol(desc, Decl(thisTypeInObjectLiterals2.ts, 63, 34)) ->ObjectDescriptor : Symbol(ObjectDescriptor, Decl(thisTypeInObjectLiterals2.ts, 53, 3)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 63, 28)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 63, 30)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 63, 28)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 63, 30)) +>makeObject : Symbol(makeObject, Decl(thisTypeInObjectLiterals2.ts, 68, 1)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 70, 28)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 70, 30)) +>desc : Symbol(desc, Decl(thisTypeInObjectLiterals2.ts, 70, 34)) +>ObjectDescriptor : Symbol(ObjectDescriptor, Decl(thisTypeInObjectLiterals2.ts, 60, 3)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 70, 28)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 70, 30)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 70, 28)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 70, 30)) let x1 = makeObject({ ->x1 : Symbol(x1, Decl(thisTypeInObjectLiterals2.ts, 65, 3)) ->makeObject : Symbol(makeObject, Decl(thisTypeInObjectLiterals2.ts, 61, 1)) +>x1 : Symbol(x1, Decl(thisTypeInObjectLiterals2.ts, 72, 3)) +>makeObject : Symbol(makeObject, Decl(thisTypeInObjectLiterals2.ts, 68, 1)) data: { x: 0, y: 0 }, ->data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 65, 21)) ->x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 66, 11)) ->y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 66, 17)) +>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 72, 21)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 73, 11)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 73, 17)) methods: { ->methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 66, 25)) +>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 73, 25)) moveBy(dx: number, dy: number) { ->moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 67, 14)) ->dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 68, 15)) ->dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 68, 26)) +>moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 74, 14)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 75, 15)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 75, 26)) this.x += dx; // Strongly typed this ->this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 66, 11)) ->x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 66, 11)) ->dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 68, 15)) +>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 73, 11)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 73, 11)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 75, 15)) this.y += dy; // Strongly typed this ->this.y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 66, 17)) ->y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 66, 17)) ->dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 68, 26)) +>this.y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 73, 17)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 73, 17)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 75, 26)) } } }); @@ -208,203 +240,367 @@ let x1 = makeObject({ // some ThisType, 'this' is of type T. type ObjectDescriptor2 = ThisType & { ->ObjectDescriptor2 : Symbol(ObjectDescriptor2, Decl(thisTypeInObjectLiterals2.ts, 73, 3)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 78, 23)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 78, 25)) +>ObjectDescriptor2 : Symbol(ObjectDescriptor2, Decl(thisTypeInObjectLiterals2.ts, 80, 3)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 85, 23)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 85, 25)) >ThisType : Symbol(ThisType, Decl(lib.d.ts, --, --)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 78, 23)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 78, 25)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 85, 23)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 85, 25)) data?: D; ->data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 78, 50)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 78, 23)) +>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 85, 50)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 85, 23)) methods?: M; ->methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 79, 13)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 78, 25)) +>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 86, 13)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 85, 25)) } declare function makeObject2(desc: ObjectDescriptor): D & M; ->makeObject2 : Symbol(makeObject2, Decl(thisTypeInObjectLiterals2.ts, 81, 1)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 83, 29)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 83, 31)) ->desc : Symbol(desc, Decl(thisTypeInObjectLiterals2.ts, 83, 35)) ->ObjectDescriptor : Symbol(ObjectDescriptor, Decl(thisTypeInObjectLiterals2.ts, 53, 3)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 83, 29)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 83, 31)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 83, 29)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 83, 31)) +>makeObject2 : Symbol(makeObject2, Decl(thisTypeInObjectLiterals2.ts, 88, 1)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 90, 29)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 90, 31)) +>desc : Symbol(desc, Decl(thisTypeInObjectLiterals2.ts, 90, 35)) +>ObjectDescriptor : Symbol(ObjectDescriptor, Decl(thisTypeInObjectLiterals2.ts, 60, 3)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 90, 29)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 90, 31)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 90, 29)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 90, 31)) let x2 = makeObject2({ ->x2 : Symbol(x2, Decl(thisTypeInObjectLiterals2.ts, 85, 3)) ->makeObject2 : Symbol(makeObject2, Decl(thisTypeInObjectLiterals2.ts, 81, 1)) +>x2 : Symbol(x2, Decl(thisTypeInObjectLiterals2.ts, 92, 3)) +>makeObject2 : Symbol(makeObject2, Decl(thisTypeInObjectLiterals2.ts, 88, 1)) data: { x: 0, y: 0 }, ->data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 85, 22)) ->x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 86, 11)) ->y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 86, 17)) +>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 92, 22)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 93, 11)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 93, 17)) methods: { ->methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 86, 25)) +>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 93, 25)) moveBy(dx: number, dy: number) { ->moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 87, 14)) ->dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 88, 15)) ->dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 88, 26)) +>moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 94, 14)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 95, 15)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 95, 26)) this.x += dx; // Strongly typed this ->this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 86, 11)) ->x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 86, 11)) ->dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 88, 15)) +>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 93, 11)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 93, 11)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 95, 15)) this.y += dy; // Strongly typed this ->this.y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 86, 17)) ->y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 86, 17)) ->dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 88, 26)) +>this.y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 93, 17)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 93, 17)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 95, 26)) } } }); +// Check pattern similar to Object.defineProperty and Object.defineProperties + +type PropDesc = { +>PropDesc : Symbol(PropDesc, Decl(thisTypeInObjectLiterals2.ts, 100, 3)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 104, 14)) + + value?: T; +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 104, 20)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 104, 14)) + + get?(): T; +>get : Symbol(get, Decl(thisTypeInObjectLiterals2.ts, 105, 14)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 104, 14)) + + set?(value: T): void; +>set : Symbol(set, Decl(thisTypeInObjectLiterals2.ts, 106, 14)) +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 107, 9)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 104, 14)) +} + +type PropDescMap = { +>PropDescMap : Symbol(PropDescMap, Decl(thisTypeInObjectLiterals2.ts, 108, 1)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 110, 17)) + + [K in keyof T]: PropDesc; +>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 111, 5)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 110, 17)) +>PropDesc : Symbol(PropDesc, Decl(thisTypeInObjectLiterals2.ts, 100, 3)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 110, 17)) +>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 111, 5)) +} + +declare function defineProp(obj: T, name: K, desc: PropDesc & ThisType): T & Record; +>defineProp : Symbol(defineProp, Decl(thisTypeInObjectLiterals2.ts, 112, 1)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 114, 28)) +>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 114, 30)) +>U : Symbol(U, Decl(thisTypeInObjectLiterals2.ts, 114, 48)) +>obj : Symbol(obj, Decl(thisTypeInObjectLiterals2.ts, 114, 52)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 114, 28)) +>name : Symbol(name, Decl(thisTypeInObjectLiterals2.ts, 114, 59)) +>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 114, 30)) +>desc : Symbol(desc, Decl(thisTypeInObjectLiterals2.ts, 114, 68)) +>PropDesc : Symbol(PropDesc, Decl(thisTypeInObjectLiterals2.ts, 100, 3)) +>U : Symbol(U, Decl(thisTypeInObjectLiterals2.ts, 114, 48)) +>ThisType : Symbol(ThisType, Decl(lib.d.ts, --, --)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 114, 28)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 114, 28)) +>Record : Symbol(Record, Decl(lib.d.ts, --, --)) +>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 114, 30)) +>U : Symbol(U, Decl(thisTypeInObjectLiterals2.ts, 114, 48)) + +declare function defineProps(obj: T, descs: PropDescMap & ThisType): T & U; +>defineProps : Symbol(defineProps, Decl(thisTypeInObjectLiterals2.ts, 114, 120)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 116, 29)) +>U : Symbol(U, Decl(thisTypeInObjectLiterals2.ts, 116, 31)) +>obj : Symbol(obj, Decl(thisTypeInObjectLiterals2.ts, 116, 35)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 116, 29)) +>descs : Symbol(descs, Decl(thisTypeInObjectLiterals2.ts, 116, 42)) +>PropDescMap : Symbol(PropDescMap, Decl(thisTypeInObjectLiterals2.ts, 108, 1)) +>U : Symbol(U, Decl(thisTypeInObjectLiterals2.ts, 116, 31)) +>ThisType : Symbol(ThisType, Decl(lib.d.ts, --, --)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 116, 29)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 116, 29)) +>U : Symbol(U, Decl(thisTypeInObjectLiterals2.ts, 116, 31)) + +let p10 = defineProp(p1, "foo", { value: 42 }); +>p10 : Symbol(p10, Decl(thisTypeInObjectLiterals2.ts, 118, 3)) +>defineProp : Symbol(defineProp, Decl(thisTypeInObjectLiterals2.ts, 112, 1)) +>p1 : Symbol(p1, Decl(thisTypeInObjectLiterals2.ts, 36, 3)) +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 118, 33)) + +p10.foo = p10.foo + 1; +>p10.foo : Symbol(foo) +>p10 : Symbol(p10, Decl(thisTypeInObjectLiterals2.ts, 118, 3)) +>foo : Symbol(foo) +>p10.foo : Symbol(foo) +>p10 : Symbol(p10, Decl(thisTypeInObjectLiterals2.ts, 118, 3)) +>foo : Symbol(foo) + +let p11 = defineProp(p1, "bar", { +>p11 : Symbol(p11, Decl(thisTypeInObjectLiterals2.ts, 121, 3)) +>defineProp : Symbol(defineProp, Decl(thisTypeInObjectLiterals2.ts, 112, 1)) +>p1 : Symbol(p1, Decl(thisTypeInObjectLiterals2.ts, 36, 3)) + + get() { +>get : Symbol(get, Decl(thisTypeInObjectLiterals2.ts, 121, 33)) + + return this.x; +>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) + + }, + set(value: number) { +>set : Symbol(set, Decl(thisTypeInObjectLiterals2.ts, 124, 6)) +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 125, 8)) + + this.x = value; +>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 125, 8)) + } +}); +p11.bar = p11.bar + 1; +>p11.bar : Symbol(bar) +>p11 : Symbol(p11, Decl(thisTypeInObjectLiterals2.ts, 121, 3)) +>bar : Symbol(bar) +>p11.bar : Symbol(bar) +>p11 : Symbol(p11, Decl(thisTypeInObjectLiterals2.ts, 121, 3)) +>bar : Symbol(bar) + +let p12 = defineProps(p1, { +>p12 : Symbol(p12, Decl(thisTypeInObjectLiterals2.ts, 131, 3)) +>defineProps : Symbol(defineProps, Decl(thisTypeInObjectLiterals2.ts, 114, 120)) +>p1 : Symbol(p1, Decl(thisTypeInObjectLiterals2.ts, 36, 3)) + + foo: { +>foo : Symbol(foo, Decl(thisTypeInObjectLiterals2.ts, 131, 27)) + + value: 42 +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 132, 10)) + + }, + bar: { +>bar : Symbol(bar, Decl(thisTypeInObjectLiterals2.ts, 134, 6)) + + get(): number { +>get : Symbol(get, Decl(thisTypeInObjectLiterals2.ts, 135, 10)) + + return this.x; +>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) + + }, + set(value: number) { +>set : Symbol(set, Decl(thisTypeInObjectLiterals2.ts, 138, 10)) +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 139, 12)) + + this.x = value; +>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 139, 12)) + } + } +}); +p12.foo = p12.foo + 1; +>p12.foo : Symbol(foo, Decl(thisTypeInObjectLiterals2.ts, 131, 27)) +>p12 : Symbol(p12, Decl(thisTypeInObjectLiterals2.ts, 131, 3)) +>foo : Symbol(foo, Decl(thisTypeInObjectLiterals2.ts, 131, 27)) +>p12.foo : Symbol(foo, Decl(thisTypeInObjectLiterals2.ts, 131, 27)) +>p12 : Symbol(p12, Decl(thisTypeInObjectLiterals2.ts, 131, 3)) +>foo : Symbol(foo, Decl(thisTypeInObjectLiterals2.ts, 131, 27)) + +p12.bar = p12.bar + 1; +>p12.bar : Symbol(bar, Decl(thisTypeInObjectLiterals2.ts, 134, 6)) +>p12 : Symbol(p12, Decl(thisTypeInObjectLiterals2.ts, 131, 3)) +>bar : Symbol(bar, Decl(thisTypeInObjectLiterals2.ts, 134, 6)) +>p12.bar : Symbol(bar, Decl(thisTypeInObjectLiterals2.ts, 134, 6)) +>p12 : Symbol(p12, Decl(thisTypeInObjectLiterals2.ts, 131, 3)) +>bar : Symbol(bar, Decl(thisTypeInObjectLiterals2.ts, 134, 6)) + // Proof of concept for typing of Vue.js type Accessors = { [K in keyof T]: (() => T[K]) | Computed }; ->Accessors : Symbol(Accessors, Decl(thisTypeInObjectLiterals2.ts, 93, 3)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 97, 15)) ->K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 97, 23)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 97, 15)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 97, 15)) ->K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 97, 23)) ->Computed : Symbol(Computed, Decl(thisTypeInObjectLiterals2.ts, 99, 39)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 97, 15)) ->K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 97, 23)) +>Accessors : Symbol(Accessors, Decl(thisTypeInObjectLiterals2.ts, 145, 22)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 149, 15)) +>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 149, 23)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 149, 15)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 149, 15)) +>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 149, 23)) +>Computed : Symbol(Computed, Decl(thisTypeInObjectLiterals2.ts, 151, 39)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 149, 15)) +>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 149, 23)) type Dictionary = { [x: string]: T } ->Dictionary : Symbol(Dictionary, Decl(thisTypeInObjectLiterals2.ts, 97, 70)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 99, 16)) ->x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 99, 24)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 99, 16)) +>Dictionary : Symbol(Dictionary, Decl(thisTypeInObjectLiterals2.ts, 149, 70)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 151, 16)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 151, 24)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 151, 16)) type Computed = { ->Computed : Symbol(Computed, Decl(thisTypeInObjectLiterals2.ts, 99, 39)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 101, 14)) +>Computed : Symbol(Computed, Decl(thisTypeInObjectLiterals2.ts, 151, 39)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 153, 14)) get?(): T; ->get : Symbol(get, Decl(thisTypeInObjectLiterals2.ts, 101, 20)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 101, 14)) +>get : Symbol(get, Decl(thisTypeInObjectLiterals2.ts, 153, 20)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 153, 14)) set?(value: T): void; ->set : Symbol(set, Decl(thisTypeInObjectLiterals2.ts, 102, 14)) ->value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 103, 9)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 101, 14)) +>set : Symbol(set, Decl(thisTypeInObjectLiterals2.ts, 154, 14)) +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 155, 9)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 153, 14)) } type VueOptions = ThisType & { ->VueOptions : Symbol(VueOptions, Decl(thisTypeInObjectLiterals2.ts, 104, 1)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 106, 16)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 106, 18)) ->P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 106, 21)) +>VueOptions : Symbol(VueOptions, Decl(thisTypeInObjectLiterals2.ts, 156, 1)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 158, 16)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 158, 18)) +>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 158, 21)) >ThisType : Symbol(ThisType, Decl(lib.d.ts, --, --)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 106, 16)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 106, 18)) ->P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 106, 21)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 158, 16)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 158, 18)) +>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 158, 21)) data?: D | (() => D); ->data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 106, 50)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 106, 16)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 106, 16)) +>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 158, 50)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 158, 16)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 158, 16)) methods?: M; ->methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 107, 25)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 106, 18)) +>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 159, 25)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 158, 18)) computed?: Accessors

; ->computed : Symbol(computed, Decl(thisTypeInObjectLiterals2.ts, 108, 16)) ->Accessors : Symbol(Accessors, Decl(thisTypeInObjectLiterals2.ts, 93, 3)) ->P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 106, 21)) +>computed : Symbol(computed, Decl(thisTypeInObjectLiterals2.ts, 160, 16)) +>Accessors : Symbol(Accessors, Decl(thisTypeInObjectLiterals2.ts, 145, 22)) +>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 158, 21)) } declare const Vue: new (options: VueOptions) => D & M & P; ->Vue : Symbol(Vue, Decl(thisTypeInObjectLiterals2.ts, 112, 13)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 112, 24)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 112, 26)) ->P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 112, 29)) ->options : Symbol(options, Decl(thisTypeInObjectLiterals2.ts, 112, 33)) ->VueOptions : Symbol(VueOptions, Decl(thisTypeInObjectLiterals2.ts, 104, 1)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 112, 24)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 112, 26)) ->P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 112, 29)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 112, 24)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 112, 26)) ->P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 112, 29)) +>Vue : Symbol(Vue, Decl(thisTypeInObjectLiterals2.ts, 164, 13)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 164, 24)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 164, 26)) +>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 164, 29)) +>options : Symbol(options, Decl(thisTypeInObjectLiterals2.ts, 164, 33)) +>VueOptions : Symbol(VueOptions, Decl(thisTypeInObjectLiterals2.ts, 156, 1)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 164, 24)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 164, 26)) +>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 164, 29)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 164, 24)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 164, 26)) +>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 164, 29)) let vue = new Vue({ ->vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 114, 3)) ->Vue : Symbol(Vue, Decl(thisTypeInObjectLiterals2.ts, 112, 13)) +>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 166, 3)) +>Vue : Symbol(Vue, Decl(thisTypeInObjectLiterals2.ts, 164, 13)) data: () => ({ x: 1, y: 2 }), ->data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 114, 19)) ->x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 115, 18)) ->y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 115, 24)) +>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 166, 19)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 167, 18)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 167, 24)) methods: { ->methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 115, 33)) +>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 167, 33)) f(x: string) { ->f : Symbol(f, Decl(thisTypeInObjectLiterals2.ts, 116, 14)) ->x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 117, 10)) +>f : Symbol(f, Decl(thisTypeInObjectLiterals2.ts, 168, 14)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 169, 10)) return this.x; ->this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 115, 18)) ->x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 115, 18)) +>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 167, 18)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 167, 18)) } }, computed: { ->computed : Symbol(computed, Decl(thisTypeInObjectLiterals2.ts, 120, 6)) +>computed : Symbol(computed, Decl(thisTypeInObjectLiterals2.ts, 172, 6)) test(): number { ->test : Symbol(test, Decl(thisTypeInObjectLiterals2.ts, 121, 15)) +>test : Symbol(test, Decl(thisTypeInObjectLiterals2.ts, 173, 15)) return this.x; ->this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 115, 18)) ->x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 115, 18)) +>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 167, 18)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 167, 18)) }, hello: { ->hello : Symbol(hello, Decl(thisTypeInObjectLiterals2.ts, 124, 10)) +>hello : Symbol(hello, Decl(thisTypeInObjectLiterals2.ts, 176, 10)) get() { ->get : Symbol(get, Decl(thisTypeInObjectLiterals2.ts, 125, 16)) +>get : Symbol(get, Decl(thisTypeInObjectLiterals2.ts, 177, 16)) return "hi"; }, set(value: string) { ->set : Symbol(set, Decl(thisTypeInObjectLiterals2.ts, 128, 14)) ->value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 129, 16)) +>set : Symbol(set, Decl(thisTypeInObjectLiterals2.ts, 180, 14)) +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 181, 16)) } } } }); vue; ->vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 114, 3)) +>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 166, 3)) vue.x; ->vue.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 115, 18)) ->vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 114, 3)) ->x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 115, 18)) +>vue.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 167, 18)) +>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 166, 3)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 167, 18)) vue.f("abc"); ->vue.f : Symbol(f, Decl(thisTypeInObjectLiterals2.ts, 116, 14)) ->vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 114, 3)) ->f : Symbol(f, Decl(thisTypeInObjectLiterals2.ts, 116, 14)) +>vue.f : Symbol(f, Decl(thisTypeInObjectLiterals2.ts, 168, 14)) +>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 166, 3)) +>f : Symbol(f, Decl(thisTypeInObjectLiterals2.ts, 168, 14)) vue.test; ->vue.test : Symbol(test, Decl(thisTypeInObjectLiterals2.ts, 121, 15)) ->vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 114, 3)) ->test : Symbol(test, Decl(thisTypeInObjectLiterals2.ts, 121, 15)) +>vue.test : Symbol(test, Decl(thisTypeInObjectLiterals2.ts, 173, 15)) +>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 166, 3)) +>test : Symbol(test, Decl(thisTypeInObjectLiterals2.ts, 173, 15)) vue.hello; ->vue.hello : Symbol(hello, Decl(thisTypeInObjectLiterals2.ts, 124, 10)) ->vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 114, 3)) ->hello : Symbol(hello, Decl(thisTypeInObjectLiterals2.ts, 124, 10)) +>vue.hello : Symbol(hello, Decl(thisTypeInObjectLiterals2.ts, 176, 10)) +>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 166, 3)) +>hello : Symbol(hello, Decl(thisTypeInObjectLiterals2.ts, 176, 10)) diff --git a/tests/baselines/reference/thisTypeInObjectLiterals2.types b/tests/baselines/reference/thisTypeInObjectLiterals2.types index 39fd922f617..cc41be6b8c6 100644 --- a/tests/baselines/reference/thisTypeInObjectLiterals2.types +++ b/tests/baselines/reference/thisTypeInObjectLiterals2.types @@ -81,16 +81,20 @@ type Point = { y: number; >y : number - moveBy(dx: number, dy: number): void; ->moveBy : (dx: number, dy: number) => void + z?: number; +>z : number | undefined + + moveBy(dx: number, dy: number, dz?: number): void; +>moveBy : (dx: number, dy: number, dz?: number | undefined) => void >dx : number >dy : number +>dz : number | undefined } let p1: Point = { >p1 : Point >Point : Point ->{ x: 10, y: 20, moveBy(dx, dy) { this.x += dx; this.y += dy; }} : { x: number; y: number; moveBy(dx: number, dy: number): void; } +>{ x: 10, y: 20, moveBy(dx, dy, dz) { this.x += dx; this.y += dy; if (this.z && dz) { this.z += dz; } }} : { x: number; y: number; moveBy(dx: number, dy: number, dz: number | undefined): void; } x: 10, >x : number @@ -100,10 +104,11 @@ let p1: Point = { >y : number >20 : 20 - moveBy(dx, dy) { ->moveBy : (dx: number, dy: number) => void + moveBy(dx, dy, dz) { +>moveBy : (dx: number, dy: number, dz: number | undefined) => void >dx : number >dy : number +>dz : number | undefined this.x += dx; >this.x += dx : number @@ -118,6 +123,21 @@ let p1: Point = { >this : Point >y : number >dy : number + + if (this.z && dz) { +>this.z && dz : number | undefined +>this.z : number | undefined +>this : Point +>z : number | undefined +>dz : number | undefined + + this.z += dz; +>this.z += dz : number +>this.z : number +>this : Point +>z : number +>dz : number + } } }; @@ -127,9 +147,9 @@ declare function f1(p: Point): void; >Point : Point f1({ ->f1({ x: 10, y: 20, moveBy(dx, dy) { this.x += dx; this.y += dy; }}) : void +>f1({ x: 10, y: 20, moveBy(dx, dy, dz) { this.x += dx; this.y += dy; if (this.z && dz) { this.z += dz; } }}) : void >f1 : (p: Point) => void ->{ x: 10, y: 20, moveBy(dx, dy) { this.x += dx; this.y += dy; }} : { x: number; y: number; moveBy(dx: number, dy: number): void; } +>{ x: 10, y: 20, moveBy(dx, dy, dz) { this.x += dx; this.y += dy; if (this.z && dz) { this.z += dz; } }} : { x: number; y: number; moveBy(dx: number, dy: number, dz: number | undefined): void; } x: 10, >x : number @@ -139,10 +159,11 @@ f1({ >y : number >20 : 20 - moveBy(dx, dy) { ->moveBy : (dx: number, dy: number) => void + moveBy(dx, dy, dz) { +>moveBy : (dx: number, dy: number, dz: number | undefined) => void >dx : number >dy : number +>dz : number | undefined this.x += dx; >this.x += dx : number @@ -157,6 +178,21 @@ f1({ >this : Point >y : number >dy : number + + if (this.z && dz) { +>this.z && dz : number | undefined +>this.z : number | undefined +>this : Point +>z : number | undefined +>dz : number | undefined + + this.z += dz; +>this.z += dz : number +>this.z : number +>this : Point +>z : number +>dz : number + } } }); @@ -169,11 +205,11 @@ type ObjectDescriptor = { >M : M data?: D; ->data : D +>data : D | undefined >D : D methods?: M & ThisType; // Type of 'this' in methods is D & M ->methods : M & ThisType +>methods : (M & ThisType) | undefined >M : M >ThisType : ThisType >D : D @@ -243,11 +279,11 @@ type ObjectDescriptor2 = ThisType & { >M : M data?: D; ->data : D +>data : D | undefined >D : D methods?: M; ->methods : M +>methods : M | undefined >M : M } @@ -302,6 +338,196 @@ let x2 = makeObject2({ } }); +// Check pattern similar to Object.defineProperty and Object.defineProperties + +type PropDesc = { +>PropDesc : PropDesc +>T : T + + value?: T; +>value : T | undefined +>T : T + + get?(): T; +>get : (() => T) | undefined +>T : T + + set?(value: T): void; +>set : ((value: T) => void) | undefined +>value : T +>T : T +} + +type PropDescMap = { +>PropDescMap : PropDescMap +>T : T + + [K in keyof T]: PropDesc; +>K : K +>T : T +>PropDesc : PropDesc +>T : T +>K : K +} + +declare function defineProp(obj: T, name: K, desc: PropDesc & ThisType): T & Record; +>defineProp : (obj: T, name: K, desc: PropDesc & ThisType) => T & Record +>T : T +>K : K +>U : U +>obj : T +>T : T +>name : K +>K : K +>desc : PropDesc & ThisType +>PropDesc : PropDesc +>U : U +>ThisType : ThisType +>T : T +>T : T +>Record : Record +>K : K +>U : U + +declare function defineProps(obj: T, descs: PropDescMap & ThisType): T & U; +>defineProps : (obj: T, descs: PropDescMap & ThisType) => T & U +>T : T +>U : U +>obj : T +>T : T +>descs : PropDescMap & ThisType +>PropDescMap : PropDescMap +>U : U +>ThisType : ThisType +>T : T +>T : T +>U : U + +let p10 = defineProp(p1, "foo", { value: 42 }); +>p10 : Point & Record<"foo", number> +>defineProp(p1, "foo", { value: 42 }) : Point & Record<"foo", number> +>defineProp : (obj: T, name: K, desc: PropDesc & ThisType) => T & Record +>p1 : Point +>"foo" : "foo" +>{ value: 42 } : { value: number; } +>value : number +>42 : 42 + +p10.foo = p10.foo + 1; +>p10.foo = p10.foo + 1 : number +>p10.foo : number +>p10 : Point & Record<"foo", number> +>foo : number +>p10.foo + 1 : number +>p10.foo : number +>p10 : Point & Record<"foo", number> +>foo : number +>1 : 1 + +let p11 = defineProp(p1, "bar", { +>p11 : Point & Record<"bar", number> +>defineProp(p1, "bar", { get() { return this.x; }, set(value: number) { this.x = value; }}) : Point & Record<"bar", number> +>defineProp : (obj: T, name: K, desc: PropDesc & ThisType) => T & Record +>p1 : Point +>"bar" : "bar" +>{ get() { return this.x; }, set(value: number) { this.x = value; }} : { get(): number; set(value: number): void; } + + get() { +>get : () => number + + return this.x; +>this.x : number +>this : Point +>x : number + + }, + set(value: number) { +>set : (value: number) => void +>value : number + + this.x = value; +>this.x = value : number +>this.x : number +>this : Point +>x : number +>value : number + } +}); +p11.bar = p11.bar + 1; +>p11.bar = p11.bar + 1 : number +>p11.bar : number +>p11 : Point & Record<"bar", number> +>bar : number +>p11.bar + 1 : number +>p11.bar : number +>p11 : Point & Record<"bar", number> +>bar : number +>1 : 1 + +let p12 = defineProps(p1, { +>p12 : Point & { foo: number; bar: number; } +>defineProps(p1, { foo: { value: 42 }, bar: { get(): number { return this.x; }, set(value: number) { this.x = value; } }}) : Point & { foo: number; bar: number; } +>defineProps : (obj: T, descs: PropDescMap & ThisType) => T & U +>p1 : Point +>{ foo: { value: 42 }, bar: { get(): number { return this.x; }, set(value: number) { this.x = value; } }} : { foo: { value: number; }; bar: { get(): number; set(value: number): void; }; } + + foo: { +>foo : { value: number; } +>{ value: 42 } : { value: number; } + + value: 42 +>value : number +>42 : 42 + + }, + bar: { +>bar : { get(): number; set(value: number): void; } +>{ get(): number { return this.x; }, set(value: number) { this.x = value; } } : { get(): number; set(value: number): void; } + + get(): number { +>get : () => number + + return this.x; +>this.x : number +>this : Point +>x : number + + }, + set(value: number) { +>set : (value: number) => void +>value : number + + this.x = value; +>this.x = value : number +>this.x : number +>this : Point +>x : number +>value : number + } + } +}); +p12.foo = p12.foo + 1; +>p12.foo = p12.foo + 1 : number +>p12.foo : number +>p12 : Point & { foo: number; bar: number; } +>foo : number +>p12.foo + 1 : number +>p12.foo : number +>p12 : Point & { foo: number; bar: number; } +>foo : number +>1 : 1 + +p12.bar = p12.bar + 1; +>p12.bar = p12.bar + 1 : number +>p12.bar : number +>p12 : Point & { foo: number; bar: number; } +>bar : number +>p12.bar + 1 : number +>p12.bar : number +>p12 : Point & { foo: number; bar: number; } +>bar : number +>1 : 1 + // Proof of concept for typing of Vue.js type Accessors = { [K in keyof T]: (() => T[K]) | Computed }; @@ -326,11 +552,11 @@ type Computed = { >T : T get?(): T; ->get : () => T +>get : (() => T) | undefined >T : T set?(value: T): void; ->set : (value: T) => void +>set : ((value: T) => void) | undefined >value : T >T : T } @@ -346,16 +572,16 @@ type VueOptions = ThisType & { >P : P data?: D | (() => D); ->data : D | (() => D) +>data : D | (() => D) | undefined >D : D >D : D methods?: M; ->methods : M +>methods : M | undefined >M : M computed?: Accessors

; ->computed : Accessors

+>computed : Accessors

| undefined >Accessors : Accessors >P : P } From 21c43009a667103d3818c6b3a03bcde1ca6654d6 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 28 Feb 2017 16:09:24 -0800 Subject: [PATCH 26/65] Enable new behavior only in --noImplicitThis mode --- src/compiler/checker.ts | 58 +++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a5c0f1819cb..6fb2e497a8d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11570,36 +11570,38 @@ namespace ts { } } } - const containingLiteral = getContainingObjectLiteral(func); - if (containingLiteral) { - // We have an object literal method. Check if the containing object literal has a contextual type - // that includes a ThisType. If so, T is the contextual type for 'this'. We continue looking in - // any directly enclosing object literals. - const contextualType = getApparentTypeOfContextualType(containingLiteral); - let literal = containingLiteral; - let type = contextualType; - while (type) { - const thisType = getThisTypeFromContextualType(type); - if (thisType) { - return instantiateType(thisType, getContextualMapper(containingLiteral)); + if (compilerOptions.noImplicitThis) { + const containingLiteral = getContainingObjectLiteral(func); + if (containingLiteral) { + // We have an object literal method. Check if the containing object literal has a contextual type + // that includes a ThisType. If so, T is the contextual type for 'this'. We continue looking in + // any directly enclosing object literals. + const contextualType = getApparentTypeOfContextualType(containingLiteral); + let literal = containingLiteral; + let type = contextualType; + while (type) { + const thisType = getThisTypeFromContextualType(type); + if (thisType) { + return instantiateType(thisType, getContextualMapper(containingLiteral)); + } + if (literal.parent.kind !== SyntaxKind.PropertyAssignment) { + break; + } + literal = literal.parent.parent; + type = getApparentTypeOfContextualType(literal); } - if (literal.parent.kind !== SyntaxKind.PropertyAssignment) { - break; - } - literal = literal.parent.parent; - type = getApparentTypeOfContextualType(literal); + // There was no contextual ThisType for the containing object literal, so the contextual type + // for 'this' is the contextual type for the containing object literal or the type of the object + // literal itself. + return contextualType || checkExpressionCached(containingLiteral); } - // There was no contextual ThisType for the containing object literal, so the contextual type - // for 'this' is the contextual type for the containing object literal or the type of the object - // literal itself. - return contextualType || checkExpressionCached(containingLiteral); - } - // In an assignment of the form 'obj.xxx = function(...)' or 'obj[xxx] = function(...)', the - // contextual type for 'this' is 'obj'. - if (func.parent.kind === SyntaxKind.BinaryExpression && (func.parent).operatorToken.kind === SyntaxKind.EqualsToken) { - const target = (func.parent).left; - if (target.kind === SyntaxKind.PropertyAccessExpression || target.kind === SyntaxKind.ElementAccessExpression) { - return checkExpressionCached((target).expression); + // In an assignment of the form 'obj.xxx = function(...)' or 'obj[xxx] = function(...)', the + // contextual type for 'this' is 'obj'. + if (func.parent.kind === SyntaxKind.BinaryExpression && (func.parent).operatorToken.kind === SyntaxKind.EqualsToken) { + const target = (func.parent).left; + if (target.kind === SyntaxKind.PropertyAccessExpression || target.kind === SyntaxKind.ElementAccessExpression) { + return checkExpressionCached((target).expression); + } } } return undefined; From 25738a8e411478896c65d983fa48840bb39db496 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 28 Feb 2017 16:09:42 -0800 Subject: [PATCH 27/65] Update tests --- tests/cases/compiler/selfInLambdas.ts | 3 +++ tests/cases/compiler/thisBinding2.ts | 3 +++ .../conformance/types/thisType/looseThisTypeInFunctions.ts | 3 +++ tests/cases/conformance/types/thisType/thisTypeInFunctions2.ts | 3 +++ .../conformance/types/thisType/thisTypeInObjectLiterals.ts | 3 +++ 5 files changed, 15 insertions(+) diff --git a/tests/cases/compiler/selfInLambdas.ts b/tests/cases/compiler/selfInLambdas.ts index 73eb5a5ce97..659b77fa458 100644 --- a/tests/cases/compiler/selfInLambdas.ts +++ b/tests/cases/compiler/selfInLambdas.ts @@ -1,3 +1,6 @@ +// @noImplicitAny: true +// @noImplicitThis: true + interface MouseEvent { x: number; y: number; diff --git a/tests/cases/compiler/thisBinding2.ts b/tests/cases/compiler/thisBinding2.ts index 5d330c9e908..b478ce9338f 100644 --- a/tests/cases/compiler/thisBinding2.ts +++ b/tests/cases/compiler/thisBinding2.ts @@ -1,3 +1,6 @@ +// @noImplicitAny: true +// @noImplicitThis: true + class C { x: number; constructor() { diff --git a/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts index b70f064f43a..0671fc78507 100644 --- a/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts +++ b/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts @@ -1,3 +1,6 @@ +// @noImplicitAny: true +// @noImplicitThis: true + interface I { n: number; explicitThis(this: this, m: number): number; diff --git a/tests/cases/conformance/types/thisType/thisTypeInFunctions2.ts b/tests/cases/conformance/types/thisType/thisTypeInFunctions2.ts index 1c80e21aa16..54dc9fa8a17 100644 --- a/tests/cases/conformance/types/thisType/thisTypeInFunctions2.ts +++ b/tests/cases/conformance/types/thisType/thisTypeInFunctions2.ts @@ -1,3 +1,6 @@ +// @noImplicitAny: true +// @noImplicitThis: true + interface IndexedWithThis { // this is a workaround for React init?: (this: this) => void; diff --git a/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals.ts b/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals.ts index 599caf70f30..00550cdf25c 100644 --- a/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals.ts +++ b/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals.ts @@ -1,3 +1,6 @@ +// @noImplicitAny: true +// @noImplicitThis: true + let o = { d: "bar", m() { From f77cd8e54bcdeb6528e091740ddaaa20063f9544 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 28 Feb 2017 16:11:05 -0800 Subject: [PATCH 28/65] Accept new baselines --- tests/baselines/reference/castTest.symbols | 6 -- tests/baselines/reference/castTest.types | 16 ++-- .../commentsOnObjectLiteral3.symbols | 7 -- .../reference/commentsOnObjectLiteral3.types | 26 ++--- ...declFileObjectLiteralWithAccessors.symbols | 3 - .../declFileObjectLiteralWithAccessors.types | 6 +- ...eclFileObjectLiteralWithOnlySetter.symbols | 3 - .../declFileObjectLiteralWithOnlySetter.types | 6 +- ...iationAssignmentWithIndexingOnLHS3.symbols | 7 -- ...ntiationAssignmentWithIndexingOnLHS3.types | 12 +-- .../reference/fatarrowfunctions.symbols | 5 - .../reference/fatarrowfunctions.types | 12 +-- .../fatarrowfunctionsInFunctions.symbols | 5 - .../fatarrowfunctionsInFunctions.types | 16 ++-- .../looseThisTypeInFunctions.errors.txt | 11 ++- .../reference/looseThisTypeInFunctions.js | 1 + .../baselines/reference/objectSpread.symbols | 3 - tests/baselines/reference/objectSpread.types | 12 +-- tests/baselines/reference/selfInLambdas.js | 1 + .../baselines/reference/selfInLambdas.symbols | 71 +++++++------- tests/baselines/reference/selfInLambdas.types | 1 + .../reference/thisBinding2.errors.txt | 28 ++++++ tests/baselines/reference/thisBinding2.js | 1 + .../reference/thisInObjectLiterals.errors.txt | 25 ----- .../reference/thisInObjectLiterals.symbols | 45 +++++++++ .../reference/thisInObjectLiterals.types | 50 ++++++++++ .../thisInPropertyBoundDeclarations.symbols | 2 - .../thisInPropertyBoundDeclarations.types | 12 +-- .../reference/thisTypeInFunctions2.errors.txt | 60 ++++++++++++ .../reference/thisTypeInFunctions2.js | 1 + .../reference/thisTypeInObjectLiterals.js | 1 + .../thisTypeInObjectLiterals.symbols | 95 ++++++++++--------- .../reference/thisTypeInObjectLiterals.types | 1 + .../throwInEnclosingStatements.symbols | 1 - .../throwInEnclosingStatements.types | 2 +- .../reference/underscoreTest1.symbols | 6 -- .../baselines/reference/underscoreTest1.types | 12 +-- 37 files changed, 346 insertions(+), 226 deletions(-) create mode 100644 tests/baselines/reference/thisBinding2.errors.txt delete mode 100644 tests/baselines/reference/thisInObjectLiterals.errors.txt create mode 100644 tests/baselines/reference/thisInObjectLiterals.symbols create mode 100644 tests/baselines/reference/thisInObjectLiterals.types create mode 100644 tests/baselines/reference/thisTypeInFunctions2.errors.txt diff --git a/tests/baselines/reference/castTest.symbols b/tests/baselines/reference/castTest.symbols index 0baee00ec47..944cc8238e6 100644 --- a/tests/baselines/reference/castTest.symbols +++ b/tests/baselines/reference/castTest.symbols @@ -71,13 +71,7 @@ var p_cast = ({ return new Point(this.x + dx, this.y + dy); >Point : Symbol(Point, Decl(castTest.ts, 11, 37)) ->this.x : Symbol(Point.x, Decl(castTest.ts, 14, 1)) ->this : Symbol(Point, Decl(castTest.ts, 11, 37)) ->x : Symbol(Point.x, Decl(castTest.ts, 14, 1)) >dx : Symbol(dx, Decl(castTest.ts, 25, 18)) ->this.y : Symbol(Point.y, Decl(castTest.ts, 15, 14)) ->this : Symbol(Point, Decl(castTest.ts, 11, 37)) ->y : Symbol(Point.y, Decl(castTest.ts, 15, 14)) >dy : Symbol(dy, Decl(castTest.ts, 25, 21)) }, diff --git a/tests/baselines/reference/castTest.types b/tests/baselines/reference/castTest.types index 08c9853dca6..666b2ccf78e 100644 --- a/tests/baselines/reference/castTest.types +++ b/tests/baselines/reference/castTest.types @@ -91,15 +91,15 @@ var p_cast = ({ return new Point(this.x + dx, this.y + dy); >new Point(this.x + dx, this.y + dy) : Point >Point : typeof Point ->this.x + dx : number ->this.x : number ->this : Point ->x : number +>this.x + dx : any +>this.x : any +>this : any +>x : any >dx : number ->this.y + dy : number ->this.y : number ->this : Point ->y : number +>this.y + dy : any +>this.y : any +>this : any +>y : any >dy : number }, diff --git a/tests/baselines/reference/commentsOnObjectLiteral3.symbols b/tests/baselines/reference/commentsOnObjectLiteral3.symbols index 34b4c706b42..3d58fe2d6d7 100644 --- a/tests/baselines/reference/commentsOnObjectLiteral3.symbols +++ b/tests/baselines/reference/commentsOnObjectLiteral3.symbols @@ -21,10 +21,6 @@ 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(v, Decl(commentsOnObjectLiteral3.ts, 1, 7)) ->prop : Symbol(prop, Decl(commentsOnObjectLiteral3.ts, 1, 9)) - } /*trailing 1*/, //setter set a(value) { @@ -32,9 +28,6 @@ var v = { >value : Symbol(value, Decl(commentsOnObjectLiteral3.ts, 14, 7)) this.prop = value; ->this.prop : Symbol(prop, Decl(commentsOnObjectLiteral3.ts, 1, 9)) ->this : Symbol(v, 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 b869e961401..4053e7e3f89 100644 --- a/tests/baselines/reference/commentsOnObjectLiteral3.types +++ b/tests/baselines/reference/commentsOnObjectLiteral3.types @@ -1,8 +1,8 @@ === tests/cases/compiler/commentsOnObjectLiteral3.ts === var v = { ->v : { prop: number; func: () => void; func1(): void; a: number; } ->{ //property prop: 1 /* multiple trailing comments */ /*trailing comments*/, //property func: function () { }, //PropertyName + CallSignature func1() { }, //getter get a() { return this.prop; } /*trailing 1*/, //setter set a(value) { this.prop = value; } // trailing 2} : { prop: number; func: () => void; func1(): void; a: number; } +>v : { prop: number; func: () => void; func1(): void; a: any; } +>{ //property prop: 1 /* multiple trailing comments */ /*trailing comments*/, //property func: function () { }, //PropertyName + CallSignature func1() { }, //getter get a() { return this.prop; } /*trailing 1*/, //setter set a(value) { this.prop = value; } // trailing 2} : { prop: number; func: () => void; func1(): void; a: any; } //property prop: 1 /* multiple trailing comments */ /*trailing comments*/, @@ -21,25 +21,25 @@ var v = { //getter get a() { ->a : number +>a : any return this.prop; ->this.prop : number ->this : { prop: number; func: () => void; func1(): void; a: number; } ->prop : number +>this.prop : any +>this : any +>prop : any } /*trailing 1*/, //setter set a(value) { ->a : number ->value : number +>a : any +>value : any this.prop = value; ->this.prop = value : number ->this.prop : number ->this : { prop: number; func: () => void; func1(): void; a: number; } ->prop : number ->value : number +>this.prop = value : any +>this.prop : any +>this : any +>prop : any +>value : any } // trailing 2 }; diff --git a/tests/baselines/reference/declFileObjectLiteralWithAccessors.symbols b/tests/baselines/reference/declFileObjectLiteralWithAccessors.symbols index df94b262c74..862b0b3781e 100644 --- a/tests/baselines/reference/declFileObjectLiteralWithAccessors.symbols +++ b/tests/baselines/reference/declFileObjectLiteralWithAccessors.symbols @@ -15,9 +15,6 @@ 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(__object, 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 1c36f321118..389b88de565 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 : number ->this : { b: number; x: number; } ->b : number +>this.b : any +>this : any +>b : any >a : number }; diff --git a/tests/baselines/reference/declFileObjectLiteralWithOnlySetter.symbols b/tests/baselines/reference/declFileObjectLiteralWithOnlySetter.symbols index 9dd2461b871..f7474466140 100644 --- a/tests/baselines/reference/declFileObjectLiteralWithOnlySetter.symbols +++ b/tests/baselines/reference/declFileObjectLiteralWithOnlySetter.symbols @@ -11,9 +11,6 @@ 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(__object, 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 bf62561f57d..2f15818e0f2 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 : number ->this : { b: number; x: number; } ->b : number +>this.b : any +>this : any +>b : any >a : number }; diff --git a/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.symbols b/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.symbols index 785a5654681..dbd5aa150dc 100644 --- a/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.symbols +++ b/tests/baselines/reference/emitCompoundExponentiationAssignmentWithIndexingOnLHS3.symbols @@ -8,18 +8,11 @@ var object = { get 0() { return this._0; ->this._0 : Symbol(_0, Decl(emitCompoundExponentiationAssignmentWithIndexingOnLHS3.ts, 1, 14)) ->this : Symbol(object, 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(object, 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 77026be2795..32e5b33e411 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 : number ->this : { _0: number; 0: number; } ->_0 : number +>this._0 : any +>this : any +>_0 : any }, set 0(x: number) { @@ -20,9 +20,9 @@ var object = { this._0 = x; >this._0 = x : number ->this._0 : number ->this : { _0: number; 0: number; } ->_0 : number +>this._0 : any +>this : any +>_0 : any >x : number }, diff --git a/tests/baselines/reference/fatarrowfunctions.symbols b/tests/baselines/reference/fatarrowfunctions.symbols index 25213a9bbf8..6ed865b0914 100644 --- a/tests/baselines/reference/fatarrowfunctions.symbols +++ b/tests/baselines/reference/fatarrowfunctions.symbols @@ -163,11 +163,6 @@ var messenger = { setTimeout(() => { this.message.toString(); }, 3000); >setTimeout : Symbol(setTimeout, Decl(fatarrowfunctions.ts, 34, 1)) ->this.message.toString : Symbol(String.toString, Decl(lib.d.ts, --, --)) ->this.message : Symbol(message, Decl(fatarrowfunctions.ts, 38, 17)) ->this : Symbol(messenger, Decl(fatarrowfunctions.ts, 38, 15)) ->message : Symbol(message, Decl(fatarrowfunctions.ts, 38, 17)) ->toString : Symbol(String.toString, Decl(lib.d.ts, --, --)) } }; diff --git a/tests/baselines/reference/fatarrowfunctions.types b/tests/baselines/reference/fatarrowfunctions.types index 1114ae365cb..304c341c916 100644 --- a/tests/baselines/reference/fatarrowfunctions.types +++ b/tests/baselines/reference/fatarrowfunctions.types @@ -234,12 +234,12 @@ var messenger = { >setTimeout(() => { this.message.toString(); }, 3000) : number >setTimeout : (expression: any, msec?: number, language?: any) => number >() => { this.message.toString(); } : () => void ->this.message.toString() : string ->this.message.toString : () => string ->this.message : string ->this : { message: string; start: () => void; } ->message : string ->toString : () => string +>this.message.toString() : any +>this.message.toString : any +>this.message : any +>this : any +>message : any +>toString : any >3000 : 3000 } }; diff --git a/tests/baselines/reference/fatarrowfunctionsInFunctions.symbols b/tests/baselines/reference/fatarrowfunctionsInFunctions.symbols index 977dd39460d..0a86affc215 100644 --- a/tests/baselines/reference/fatarrowfunctionsInFunctions.symbols +++ b/tests/baselines/reference/fatarrowfunctionsInFunctions.symbols @@ -16,17 +16,12 @@ var messenger = { var _self = this; >_self : Symbol(_self, Decl(fatarrowfunctionsInFunctions.ts, 5, 11)) ->this : Symbol(messenger, Decl(fatarrowfunctionsInFunctions.ts, 2, 15)) setTimeout(function() { >setTimeout : Symbol(setTimeout, Decl(fatarrowfunctionsInFunctions.ts, 0, 0)) _self.message.toString(); ->_self.message.toString : Symbol(String.toString, Decl(lib.d.ts, --, --)) ->_self.message : Symbol(message, Decl(fatarrowfunctionsInFunctions.ts, 2, 17)) >_self : Symbol(_self, Decl(fatarrowfunctionsInFunctions.ts, 5, 11)) ->message : Symbol(message, Decl(fatarrowfunctionsInFunctions.ts, 2, 17)) ->toString : Symbol(String.toString, Decl(lib.d.ts, --, --)) }, 3000); } diff --git a/tests/baselines/reference/fatarrowfunctionsInFunctions.types b/tests/baselines/reference/fatarrowfunctionsInFunctions.types index 88807f2a37b..8b9bd7ccd7a 100644 --- a/tests/baselines/reference/fatarrowfunctionsInFunctions.types +++ b/tests/baselines/reference/fatarrowfunctionsInFunctions.types @@ -18,8 +18,8 @@ var messenger = { >function() { var _self = this; setTimeout(function() { _self.message.toString(); }, 3000); } : () => void var _self = this; ->_self : { message: string; start: () => void; } ->this : { message: string; start: () => void; } +>_self : any +>this : any setTimeout(function() { >setTimeout(function() { _self.message.toString(); }, 3000) : number @@ -27,12 +27,12 @@ var messenger = { >function() { _self.message.toString(); } : () => void _self.message.toString(); ->_self.message.toString() : string ->_self.message.toString : () => string ->_self.message : string ->_self : { message: string; start: () => void; } ->message : string ->toString : () => string +>_self.message.toString() : any +>_self.message.toString : any +>_self.message : any +>_self : any +>message : any +>toString : any }, 3000); >3000 : 3000 diff --git a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt index 7e12a714406..cf4dcbd7dd5 100644 --- a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt +++ b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt @@ -1,13 +1,14 @@ -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'. +tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(22,1): error TS2322: Type '(this: C, m: number) => number' is not assignable to type '(this: void, m: number) => number'. The 'this' types of each signature are incompatible. Type 'void' is not assignable to type 'C'. -tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(25,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 TS2684: The 'this' context of type 'void' is not assignable to method's 'this' of type 'I'. -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(26,27): error TS2339: Property 'length' does not exist on type 'number'. +tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(34,28): error TS2339: Property 'length' does not exist on type 'number'. +tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(38,9): error TS2684: The 'this' context of type 'void' is not assignable to method's 'this' of type 'I'. +tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(47,20): error TS2339: Property 'length' does not exist on type 'number'. ==== tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts (5 errors) ==== + interface I { n: number; explicitThis(this: this, m: number): number; diff --git a/tests/baselines/reference/looseThisTypeInFunctions.js b/tests/baselines/reference/looseThisTypeInFunctions.js index cb1fbcc8b95..3e97691ade2 100644 --- a/tests/baselines/reference/looseThisTypeInFunctions.js +++ b/tests/baselines/reference/looseThisTypeInFunctions.js @@ -1,4 +1,5 @@ //// [looseThisTypeInFunctions.ts] + interface I { n: number; explicitThis(this: this, m: number): number; diff --git a/tests/baselines/reference/objectSpread.symbols b/tests/baselines/reference/objectSpread.symbols index 0538121e90c..1ec2520e166 100644 --- a/tests/baselines/reference/objectSpread.symbols +++ b/tests/baselines/reference/objectSpread.symbols @@ -200,9 +200,6 @@ let cplus: { p: number, plus(): void } = { ...c, plus() { return this.p + 1; } } >plus : Symbol(plus, Decl(objectSpread.ts, 49, 23)) >c : Symbol(c, Decl(objectSpread.ts, 45, 3)) >plus : Symbol(plus, Decl(objectSpread.ts, 49, 48)) ->this.p : Symbol(p, Decl(objectSpread.ts, 49, 12)) ->this : Symbol(cplus, Decl(objectSpread.ts, 49, 10)) ->p : Symbol(p, Decl(objectSpread.ts, 49, 12)) cplus.plus(); >cplus.plus : Symbol(plus, Decl(objectSpread.ts, 49, 23)) diff --git a/tests/baselines/reference/objectSpread.types b/tests/baselines/reference/objectSpread.types index 3a736721425..950dab43465 100644 --- a/tests/baselines/reference/objectSpread.types +++ b/tests/baselines/reference/objectSpread.types @@ -263,13 +263,13 @@ let cplus: { p: number, plus(): void } = { ...c, plus() { return this.p + 1; } } >cplus : { p: number; plus(): void; } >p : number >plus : () => void ->{ ...c, plus() { return this.p + 1; } } : { plus(): number; p: number; } +>{ ...c, plus() { return this.p + 1; } } : { plus(): any; p: number; } >c : C ->plus : () => number ->this.p + 1 : number ->this.p : number ->this : { p: number; plus(): void; } ->p : number +>plus : () => any +>this.p + 1 : any +>this.p : any +>this : any +>p : any >1 : 1 cplus.plus(); diff --git a/tests/baselines/reference/selfInLambdas.js b/tests/baselines/reference/selfInLambdas.js index b143c0c9e4e..f9654606716 100644 --- a/tests/baselines/reference/selfInLambdas.js +++ b/tests/baselines/reference/selfInLambdas.js @@ -1,4 +1,5 @@ //// [selfInLambdas.ts] + interface MouseEvent { x: number; y: number; diff --git a/tests/baselines/reference/selfInLambdas.symbols b/tests/baselines/reference/selfInLambdas.symbols index 0a51113710b..8efadb7c077 100644 --- a/tests/baselines/reference/selfInLambdas.symbols +++ b/tests/baselines/reference/selfInLambdas.symbols @@ -1,51 +1,52 @@ === tests/cases/compiler/selfInLambdas.ts === + interface MouseEvent { >MouseEvent : Symbol(MouseEvent, Decl(selfInLambdas.ts, 0, 0)) x: number; ->x : Symbol(MouseEvent.x, Decl(selfInLambdas.ts, 0, 22)) +>x : Symbol(MouseEvent.x, Decl(selfInLambdas.ts, 1, 22)) y: number; ->y : Symbol(MouseEvent.y, Decl(selfInLambdas.ts, 1, 14)) +>y : Symbol(MouseEvent.y, Decl(selfInLambdas.ts, 2, 14)) } declare var window: Window; ->window : Symbol(window, Decl(selfInLambdas.ts, 5, 11)) ->Window : Symbol(Window, Decl(selfInLambdas.ts, 5, 27)) +>window : Symbol(window, Decl(selfInLambdas.ts, 6, 11)) +>Window : Symbol(Window, Decl(selfInLambdas.ts, 6, 27)) interface Window { ->Window : Symbol(Window, Decl(selfInLambdas.ts, 5, 27)) +>Window : Symbol(Window, Decl(selfInLambdas.ts, 6, 27)) onmousemove: (ev: MouseEvent) => any; ->onmousemove : Symbol(Window.onmousemove, Decl(selfInLambdas.ts, 6, 18)) ->ev : Symbol(ev, Decl(selfInLambdas.ts, 7, 18)) +>onmousemove : Symbol(Window.onmousemove, Decl(selfInLambdas.ts, 7, 18)) +>ev : Symbol(ev, Decl(selfInLambdas.ts, 8, 18)) >MouseEvent : Symbol(MouseEvent, Decl(selfInLambdas.ts, 0, 0)) } var o = { ->o : Symbol(o, Decl(selfInLambdas.ts, 10, 3)) +>o : Symbol(o, Decl(selfInLambdas.ts, 11, 3)) counter: 0, ->counter : Symbol(counter, Decl(selfInLambdas.ts, 10, 9)) +>counter : Symbol(counter, Decl(selfInLambdas.ts, 11, 9)) start: function() { ->start : Symbol(start, Decl(selfInLambdas.ts, 12, 15)) +>start : Symbol(start, Decl(selfInLambdas.ts, 13, 15)) window.onmousemove = () => { ->window.onmousemove : Symbol(Window.onmousemove, Decl(selfInLambdas.ts, 6, 18)) ->window : Symbol(window, Decl(selfInLambdas.ts, 5, 11)) ->onmousemove : Symbol(Window.onmousemove, Decl(selfInLambdas.ts, 6, 18)) +>window.onmousemove : Symbol(Window.onmousemove, Decl(selfInLambdas.ts, 7, 18)) +>window : Symbol(window, Decl(selfInLambdas.ts, 6, 11)) +>onmousemove : Symbol(Window.onmousemove, Decl(selfInLambdas.ts, 7, 18)) this.counter++ ->this.counter : Symbol(counter, Decl(selfInLambdas.ts, 10, 9)) ->this : Symbol(o, Decl(selfInLambdas.ts, 10, 7)) ->counter : Symbol(counter, Decl(selfInLambdas.ts, 10, 9)) +>this.counter : Symbol(counter, Decl(selfInLambdas.ts, 11, 9)) +>this : Symbol(o, Decl(selfInLambdas.ts, 11, 7)) +>counter : Symbol(counter, Decl(selfInLambdas.ts, 11, 9)) var f = () => this.counter; ->f : Symbol(f, Decl(selfInLambdas.ts, 18, 15)) ->this.counter : Symbol(counter, Decl(selfInLambdas.ts, 10, 9)) ->this : Symbol(o, Decl(selfInLambdas.ts, 10, 7)) ->counter : Symbol(counter, Decl(selfInLambdas.ts, 10, 9)) +>f : Symbol(f, Decl(selfInLambdas.ts, 19, 15)) +>this.counter : Symbol(counter, Decl(selfInLambdas.ts, 11, 9)) +>this : Symbol(o, Decl(selfInLambdas.ts, 11, 7)) +>counter : Symbol(counter, Decl(selfInLambdas.ts, 11, 9)) } @@ -56,39 +57,39 @@ var o = { class X { ->X : Symbol(X, Decl(selfInLambdas.ts, 24, 1)) +>X : Symbol(X, Decl(selfInLambdas.ts, 25, 1)) private value = "value"; ->value : Symbol(X.value, Decl(selfInLambdas.ts, 28, 9)) +>value : Symbol(X.value, Decl(selfInLambdas.ts, 29, 9)) public foo() { ->foo : Symbol(X.foo, Decl(selfInLambdas.ts, 29, 25)) +>foo : Symbol(X.foo, Decl(selfInLambdas.ts, 30, 25)) var outer= () => { ->outer : Symbol(outer, Decl(selfInLambdas.ts, 32, 5)) +>outer : Symbol(outer, Decl(selfInLambdas.ts, 33, 5)) var x = this.value; ->x : Symbol(x, Decl(selfInLambdas.ts, 33, 15)) ->this.value : Symbol(X.value, Decl(selfInLambdas.ts, 28, 9)) ->this : Symbol(X, Decl(selfInLambdas.ts, 24, 1)) ->value : Symbol(X.value, Decl(selfInLambdas.ts, 28, 9)) +>x : Symbol(x, Decl(selfInLambdas.ts, 34, 15)) +>this.value : Symbol(X.value, Decl(selfInLambdas.ts, 29, 9)) +>this : Symbol(X, Decl(selfInLambdas.ts, 25, 1)) +>value : Symbol(X.value, Decl(selfInLambdas.ts, 29, 9)) var inner = () => { ->inner : Symbol(inner, Decl(selfInLambdas.ts, 34, 15)) +>inner : Symbol(inner, Decl(selfInLambdas.ts, 35, 15)) var y = this.value; ->y : Symbol(y, Decl(selfInLambdas.ts, 35, 19)) ->this.value : Symbol(X.value, Decl(selfInLambdas.ts, 28, 9)) ->this : Symbol(X, Decl(selfInLambdas.ts, 24, 1)) ->value : Symbol(X.value, Decl(selfInLambdas.ts, 28, 9)) +>y : Symbol(y, Decl(selfInLambdas.ts, 36, 19)) +>this.value : Symbol(X.value, Decl(selfInLambdas.ts, 29, 9)) +>this : Symbol(X, Decl(selfInLambdas.ts, 25, 1)) +>value : Symbol(X.value, Decl(selfInLambdas.ts, 29, 9)) } inner(); ->inner : Symbol(inner, Decl(selfInLambdas.ts, 34, 15)) +>inner : Symbol(inner, Decl(selfInLambdas.ts, 35, 15)) }; outer(); ->outer : Symbol(outer, Decl(selfInLambdas.ts, 32, 5)) +>outer : Symbol(outer, Decl(selfInLambdas.ts, 33, 5)) } } diff --git a/tests/baselines/reference/selfInLambdas.types b/tests/baselines/reference/selfInLambdas.types index a26e1e0bf28..251cfb2d0c3 100644 --- a/tests/baselines/reference/selfInLambdas.types +++ b/tests/baselines/reference/selfInLambdas.types @@ -1,4 +1,5 @@ === tests/cases/compiler/selfInLambdas.ts === + interface MouseEvent { >MouseEvent : MouseEvent diff --git a/tests/baselines/reference/thisBinding2.errors.txt b/tests/baselines/reference/thisBinding2.errors.txt new file mode 100644 index 00000000000..ddfa078a2d2 --- /dev/null +++ b/tests/baselines/reference/thisBinding2.errors.txt @@ -0,0 +1,28 @@ +tests/cases/compiler/thisBinding2.ts(11,11): error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation. + + +==== tests/cases/compiler/thisBinding2.ts (1 errors) ==== + + class C { + x: number; + constructor() { + this.x = (() => { + var x = 1; + return this.x; + })(); + this.x = function() { + var x = 1; + return this.x; + ~~~~ +!!! error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation. + }(); + } + } + declare function setTimeout(expression: any, msec?: number, language?: any): number; + var messenger = { + message: "Hello World", + start: function () { + return setTimeout(() => { var x = this.message; }, 3000); + } + }; + \ No newline at end of file diff --git a/tests/baselines/reference/thisBinding2.js b/tests/baselines/reference/thisBinding2.js index 142cd9db4a5..732cb4fac00 100644 --- a/tests/baselines/reference/thisBinding2.js +++ b/tests/baselines/reference/thisBinding2.js @@ -1,4 +1,5 @@ //// [thisBinding2.ts] + class C { x: number; constructor() { diff --git a/tests/baselines/reference/thisInObjectLiterals.errors.txt b/tests/baselines/reference/thisInObjectLiterals.errors.txt deleted file mode 100644 index 3da8430802d..00000000000 --- a/tests/baselines/reference/thisInObjectLiterals.errors.txt +++ /dev/null @@ -1,25 +0,0 @@ -tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts(15,21): error TS2339: Property 'spaaace' does not exist on type '{ f(): any; }'. - - -==== tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts (1 errors) ==== - class MyClass { - t: number; - - fn() { - type ContainingThis = this; - //type of 'this' in an object literal is the containing scope's this - var t = { x: this, y: this.t }; - var t: { x: ContainingThis; y: number }; - } - } - - //type of 'this' in an object literal method is the type of the object literal - var obj = { - f() { - return this.spaaace; - ~~~~~~~ -!!! error TS2339: Property 'spaaace' does not exist on type '{ f(): any; }'. - } - }; - var obj: { f: () => any; }; - \ No newline at end of file diff --git a/tests/baselines/reference/thisInObjectLiterals.symbols b/tests/baselines/reference/thisInObjectLiterals.symbols new file mode 100644 index 00000000000..51f30009b65 --- /dev/null +++ b/tests/baselines/reference/thisInObjectLiterals.symbols @@ -0,0 +1,45 @@ +=== tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts === +class MyClass { +>MyClass : Symbol(MyClass, Decl(thisInObjectLiterals.ts, 0, 0)) + + t: number; +>t : Symbol(MyClass.t, Decl(thisInObjectLiterals.ts, 0, 15)) + + fn() { +>fn : Symbol(MyClass.fn, Decl(thisInObjectLiterals.ts, 1, 14)) + + type ContainingThis = this; +>ContainingThis : Symbol(ContainingThis, Decl(thisInObjectLiterals.ts, 3, 10)) + + //type of 'this' in an object literal is the containing scope's this + var t = { x: this, y: this.t }; +>t : Symbol(t, Decl(thisInObjectLiterals.ts, 6, 11), Decl(thisInObjectLiterals.ts, 7, 11)) +>x : Symbol(x, Decl(thisInObjectLiterals.ts, 6, 17)) +>this : Symbol(MyClass, Decl(thisInObjectLiterals.ts, 0, 0)) +>y : Symbol(y, Decl(thisInObjectLiterals.ts, 6, 26)) +>this.t : Symbol(MyClass.t, Decl(thisInObjectLiterals.ts, 0, 15)) +>this : Symbol(MyClass, Decl(thisInObjectLiterals.ts, 0, 0)) +>t : Symbol(MyClass.t, Decl(thisInObjectLiterals.ts, 0, 15)) + + var t: { x: ContainingThis; y: number }; +>t : Symbol(t, Decl(thisInObjectLiterals.ts, 6, 11), Decl(thisInObjectLiterals.ts, 7, 11)) +>x : Symbol(x, Decl(thisInObjectLiterals.ts, 7, 16)) +>ContainingThis : Symbol(ContainingThis, Decl(thisInObjectLiterals.ts, 3, 10)) +>y : Symbol(y, Decl(thisInObjectLiterals.ts, 7, 35)) + } +} + +//type of 'this' in an object literal method is the type of the object literal +var obj = { +>obj : Symbol(obj, Decl(thisInObjectLiterals.ts, 12, 3), Decl(thisInObjectLiterals.ts, 17, 3)) + + f() { +>f : Symbol(f, Decl(thisInObjectLiterals.ts, 12, 11)) + + return this.spaaace; + } +}; +var obj: { f: () => any; }; +>obj : Symbol(obj, Decl(thisInObjectLiterals.ts, 12, 3), Decl(thisInObjectLiterals.ts, 17, 3)) +>f : Symbol(f, Decl(thisInObjectLiterals.ts, 17, 10)) + diff --git a/tests/baselines/reference/thisInObjectLiterals.types b/tests/baselines/reference/thisInObjectLiterals.types new file mode 100644 index 00000000000..b707a473dfb --- /dev/null +++ b/tests/baselines/reference/thisInObjectLiterals.types @@ -0,0 +1,50 @@ +=== tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts === +class MyClass { +>MyClass : MyClass + + t: number; +>t : number + + fn() { +>fn : () => void + + type ContainingThis = this; +>ContainingThis : this + + //type of 'this' in an object literal is the containing scope's this + var t = { x: this, y: this.t }; +>t : { x: this; y: number; } +>{ x: this, y: this.t } : { x: this; y: number; } +>x : this +>this : this +>y : number +>this.t : number +>this : this +>t : number + + var t: { x: ContainingThis; y: number }; +>t : { x: this; y: number; } +>x : this +>ContainingThis : this +>y : number + } +} + +//type of 'this' in an object literal method is the type of the object literal +var obj = { +>obj : { f(): any; } +>{ f() { return this.spaaace; }} : { f(): any; } + + f() { +>f : () => any + + return this.spaaace; +>this.spaaace : any +>this : any +>spaaace : any + } +}; +var obj: { f: () => any; }; +>obj : { f(): any; } +>f : () => any + diff --git a/tests/baselines/reference/thisInPropertyBoundDeclarations.symbols b/tests/baselines/reference/thisInPropertyBoundDeclarations.symbols index 6afdd73f77f..12d3b2db31e 100644 --- a/tests/baselines/reference/thisInPropertyBoundDeclarations.symbols +++ b/tests/baselines/reference/thisInPropertyBoundDeclarations.symbols @@ -70,7 +70,6 @@ class A { a: function() { return this; }, >a : Symbol(a, Decl(thisInPropertyBoundDeclarations.ts, 33, 13)) ->this : Symbol(__object, Decl(thisInPropertyBoundDeclarations.ts, 33, 11)) }; @@ -80,7 +79,6 @@ class A { return { a: function() { return this; }, >a : Symbol(a, Decl(thisInPropertyBoundDeclarations.ts, 38, 16)) ->this : Symbol(__object, Decl(thisInPropertyBoundDeclarations.ts, 38, 14)) }; }; diff --git a/tests/baselines/reference/thisInPropertyBoundDeclarations.types b/tests/baselines/reference/thisInPropertyBoundDeclarations.types index 7c2b28bfb3e..b783c5c1b5f 100644 --- a/tests/baselines/reference/thisInPropertyBoundDeclarations.types +++ b/tests/baselines/reference/thisInPropertyBoundDeclarations.types @@ -84,9 +84,9 @@ class A { >{ a: function() { return this; }, } : { a: () => any; } a: function() { return this; }, ->a : () => { a: any; } ->function() { return this; } : () => { a: any; } ->this : { a: () => any; } +>a : () => any +>function() { return this; } : () => any +>this : any }; @@ -98,9 +98,9 @@ class A { >{ a: function() { return this; }, } : { a: () => any; } a: function() { return this; }, ->a : () => { a: any; } ->function() { return this; } : () => { a: any; } ->this : { a: () => any; } +>a : () => any +>function() { return this; } : () => any +>this : any }; }; diff --git a/tests/baselines/reference/thisTypeInFunctions2.errors.txt b/tests/baselines/reference/thisTypeInFunctions2.errors.txt new file mode 100644 index 00000000000..86721a76971 --- /dev/null +++ b/tests/baselines/reference/thisTypeInFunctions2.errors.txt @@ -0,0 +1,60 @@ +tests/cases/conformance/types/thisType/thisTypeInFunctions2.ts(15,5): error TS7010: 'foo', which lacks return-type annotation, implicitly has an 'any' return type. + + +==== tests/cases/conformance/types/thisType/thisTypeInFunctions2.ts (1 errors) ==== + + interface IndexedWithThis { + // this is a workaround for React + init?: (this: this) => void; + willDestroy?: (this: any) => void; + [propName: string]: number | string | boolean | symbol | undefined | null | {} | ((this: any, ...args:any[]) => any); + } + interface IndexedWithoutThis { + // this is what React would like to write (and what they write today) + init?: () => void; + willDestroy?: () => void; + [propName: string]: any; + } + interface SimpleInterface { + foo(n: string); + ~~~~~~~~~~~~~~~ +!!! error TS7010: 'foo', which lacks return-type annotation, implicitly has an 'any' return type. + bar(): number; + } + declare function extend1(args: IndexedWithThis): void; + declare function extend2(args: IndexedWithoutThis): void; + declare function simple(arg: SimpleInterface): void; + + extend1({ + init() { + this // this: IndexedWithThis because of contextual typing. + // this.mine + this.willDestroy + }, + mine: 12, + foo() { + this.url; // this: any because 'foo' matches the string indexer + this.willDestroy; + } + }); + extend2({ + init() { + this // this: containing object literal type + this.mine + }, + mine: 13, + foo() { + this // this: containing object literal type + this.mine + } + }); + + simple({ + foo(n) { + return n.length + this.bar(); + }, + bar() { + return 14; + } + }) + \ No newline at end of file diff --git a/tests/baselines/reference/thisTypeInFunctions2.js b/tests/baselines/reference/thisTypeInFunctions2.js index 978f79483b0..7608629ea89 100644 --- a/tests/baselines/reference/thisTypeInFunctions2.js +++ b/tests/baselines/reference/thisTypeInFunctions2.js @@ -1,4 +1,5 @@ //// [thisTypeInFunctions2.ts] + interface IndexedWithThis { // this is a workaround for React init?: (this: this) => void; diff --git a/tests/baselines/reference/thisTypeInObjectLiterals.js b/tests/baselines/reference/thisTypeInObjectLiterals.js index 342c9d58c84..18f0a6407bc 100644 --- a/tests/baselines/reference/thisTypeInObjectLiterals.js +++ b/tests/baselines/reference/thisTypeInObjectLiterals.js @@ -1,4 +1,5 @@ //// [thisTypeInObjectLiterals.ts] + let o = { d: "bar", m() { diff --git a/tests/baselines/reference/thisTypeInObjectLiterals.symbols b/tests/baselines/reference/thisTypeInObjectLiterals.symbols index fd6d6ecebd5..374c790bd8f 100644 --- a/tests/baselines/reference/thisTypeInObjectLiterals.symbols +++ b/tests/baselines/reference/thisTypeInObjectLiterals.symbols @@ -1,104 +1,105 @@ === tests/cases/conformance/types/thisType/thisTypeInObjectLiterals.ts === + let o = { ->o : Symbol(o, Decl(thisTypeInObjectLiterals.ts, 0, 3)) +>o : Symbol(o, Decl(thisTypeInObjectLiterals.ts, 1, 3)) d: "bar", ->d : Symbol(d, Decl(thisTypeInObjectLiterals.ts, 0, 9)) +>d : Symbol(d, Decl(thisTypeInObjectLiterals.ts, 1, 9)) m() { ->m : Symbol(m, Decl(thisTypeInObjectLiterals.ts, 1, 13)) +>m : Symbol(m, Decl(thisTypeInObjectLiterals.ts, 2, 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(o, Decl(thisTypeInObjectLiterals.ts, 0, 7)) ->d : Symbol(d, Decl(thisTypeInObjectLiterals.ts, 0, 9)) +>this.d : Symbol(d, Decl(thisTypeInObjectLiterals.ts, 1, 9)) +>this : Symbol(o, Decl(thisTypeInObjectLiterals.ts, 1, 7)) +>d : Symbol(d, Decl(thisTypeInObjectLiterals.ts, 1, 9)) >length : Symbol(String.length, Decl(lib.d.ts, --, --)) }, f: function() { ->f : Symbol(f, Decl(thisTypeInObjectLiterals.ts, 4, 6)) +>f : Symbol(f, Decl(thisTypeInObjectLiterals.ts, 5, 6)) 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(o, Decl(thisTypeInObjectLiterals.ts, 0, 7)) ->d : Symbol(d, Decl(thisTypeInObjectLiterals.ts, 0, 9)) +>this.d : Symbol(d, Decl(thisTypeInObjectLiterals.ts, 1, 9)) +>this : Symbol(o, Decl(thisTypeInObjectLiterals.ts, 1, 7)) +>d : Symbol(d, Decl(thisTypeInObjectLiterals.ts, 1, 9)) >length : Symbol(String.length, Decl(lib.d.ts, --, --)) } } let mutuallyRecursive = { ->mutuallyRecursive : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 10, 3)) +>mutuallyRecursive : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 11, 3)) a: 100, ->a : Symbol(a, Decl(thisTypeInObjectLiterals.ts, 10, 25)) +>a : Symbol(a, Decl(thisTypeInObjectLiterals.ts, 11, 25)) start() { ->start : Symbol(start, Decl(thisTypeInObjectLiterals.ts, 11, 11)) +>start : Symbol(start, Decl(thisTypeInObjectLiterals.ts, 12, 11)) return this.passthrough(this.a); ->this.passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 14, 6)) ->this : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 10, 23)) ->passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 14, 6)) ->this.a : Symbol(a, Decl(thisTypeInObjectLiterals.ts, 10, 25)) ->this : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 10, 23)) ->a : Symbol(a, Decl(thisTypeInObjectLiterals.ts, 10, 25)) +>this.passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 15, 6)) +>this : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 11, 23)) +>passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 15, 6)) +>this.a : Symbol(a, Decl(thisTypeInObjectLiterals.ts, 11, 25)) +>this : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 11, 23)) +>a : Symbol(a, Decl(thisTypeInObjectLiterals.ts, 11, 25)) }, passthrough(n: number) { ->passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 14, 6)) ->n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 15, 16)) +>passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 15, 6)) +>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 16, 16)) return this.sub1(n); ->this.sub1 : Symbol(sub1, Decl(thisTypeInObjectLiterals.ts, 17, 6)) ->this : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 10, 23)) ->sub1 : Symbol(sub1, Decl(thisTypeInObjectLiterals.ts, 17, 6)) ->n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 15, 16)) +>this.sub1 : Symbol(sub1, Decl(thisTypeInObjectLiterals.ts, 18, 6)) +>this : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 11, 23)) +>sub1 : Symbol(sub1, Decl(thisTypeInObjectLiterals.ts, 18, 6)) +>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 16, 16)) }, sub1(n: number): number { ->sub1 : Symbol(sub1, Decl(thisTypeInObjectLiterals.ts, 17, 6)) ->n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 18, 9)) +>sub1 : Symbol(sub1, Decl(thisTypeInObjectLiterals.ts, 18, 6)) +>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 19, 9)) if (n > 0) { ->n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 18, 9)) +>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 19, 9)) return this.passthrough(n - 1); ->this.passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 14, 6)) ->this : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 10, 23)) ->passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 14, 6)) ->n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 18, 9)) +>this.passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 15, 6)) +>this : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 11, 23)) +>passthrough : Symbol(passthrough, Decl(thisTypeInObjectLiterals.ts, 15, 6)) +>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 19, 9)) } return n; ->n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 18, 9)) +>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 19, 9)) } } var i: number = mutuallyRecursive.start(); ->i : Symbol(i, Decl(thisTypeInObjectLiterals.ts, 25, 3)) ->mutuallyRecursive.start : Symbol(start, Decl(thisTypeInObjectLiterals.ts, 11, 11)) ->mutuallyRecursive : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 10, 3)) ->start : Symbol(start, Decl(thisTypeInObjectLiterals.ts, 11, 11)) +>i : Symbol(i, Decl(thisTypeInObjectLiterals.ts, 26, 3)) +>mutuallyRecursive.start : Symbol(start, Decl(thisTypeInObjectLiterals.ts, 12, 11)) +>mutuallyRecursive : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 11, 3)) +>start : Symbol(start, Decl(thisTypeInObjectLiterals.ts, 12, 11)) interface I { ->I : Symbol(I, Decl(thisTypeInObjectLiterals.ts, 25, 42)) +>I : Symbol(I, Decl(thisTypeInObjectLiterals.ts, 26, 42)) a: number; ->a : Symbol(I.a, Decl(thisTypeInObjectLiterals.ts, 26, 13)) +>a : Symbol(I.a, Decl(thisTypeInObjectLiterals.ts, 27, 13)) start(): number; ->start : Symbol(I.start, Decl(thisTypeInObjectLiterals.ts, 27, 14)) +>start : Symbol(I.start, Decl(thisTypeInObjectLiterals.ts, 28, 14)) passthrough(n: number): number; ->passthrough : Symbol(I.passthrough, Decl(thisTypeInObjectLiterals.ts, 28, 20)) ->n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 29, 16)) +>passthrough : Symbol(I.passthrough, Decl(thisTypeInObjectLiterals.ts, 29, 20)) +>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 30, 16)) sub1(n: number): number; ->sub1 : Symbol(I.sub1, Decl(thisTypeInObjectLiterals.ts, 29, 35)) ->n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 30, 9)) +>sub1 : Symbol(I.sub1, Decl(thisTypeInObjectLiterals.ts, 30, 35)) +>n : Symbol(n, Decl(thisTypeInObjectLiterals.ts, 31, 9)) } var impl: I = mutuallyRecursive; ->impl : Symbol(impl, Decl(thisTypeInObjectLiterals.ts, 32, 3)) ->I : Symbol(I, Decl(thisTypeInObjectLiterals.ts, 25, 42)) ->mutuallyRecursive : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 10, 3)) +>impl : Symbol(impl, Decl(thisTypeInObjectLiterals.ts, 33, 3)) +>I : Symbol(I, Decl(thisTypeInObjectLiterals.ts, 26, 42)) +>mutuallyRecursive : Symbol(mutuallyRecursive, Decl(thisTypeInObjectLiterals.ts, 11, 3)) diff --git a/tests/baselines/reference/thisTypeInObjectLiterals.types b/tests/baselines/reference/thisTypeInObjectLiterals.types index d5c6d851faf..d4e6188b9cf 100644 --- a/tests/baselines/reference/thisTypeInObjectLiterals.types +++ b/tests/baselines/reference/thisTypeInObjectLiterals.types @@ -1,4 +1,5 @@ === tests/cases/conformance/types/thisType/thisTypeInObjectLiterals.ts === + let o = { >o : { d: string; m(): number; f: () => number; } >{ d: "bar", m() { return this.d.length; }, f: function() { return this.d.length; }} : { d: string; m(): number; f: () => number; } diff --git a/tests/baselines/reference/throwInEnclosingStatements.symbols b/tests/baselines/reference/throwInEnclosingStatements.symbols index 36dcd3cfcbd..63ed9dde578 100644 --- a/tests/baselines/reference/throwInEnclosingStatements.symbols +++ b/tests/baselines/reference/throwInEnclosingStatements.symbols @@ -89,7 +89,6 @@ var aa = { >biz : Symbol(biz, Decl(throwInEnclosingStatements.ts, 41, 10)) throw this; ->this : Symbol(aa, Decl(throwInEnclosingStatements.ts, 40, 8)) } } diff --git a/tests/baselines/reference/throwInEnclosingStatements.types b/tests/baselines/reference/throwInEnclosingStatements.types index d859bbd6392..2d99ac435ae 100644 --- a/tests/baselines/reference/throwInEnclosingStatements.types +++ b/tests/baselines/reference/throwInEnclosingStatements.types @@ -104,7 +104,7 @@ var aa = { >biz : () => void throw this; ->this : { id: number; biz(): void; } +>this : any } } diff --git a/tests/baselines/reference/underscoreTest1.symbols b/tests/baselines/reference/underscoreTest1.symbols index 3b578be8165..41b0c811027 100644 --- a/tests/baselines/reference/underscoreTest1.symbols +++ b/tests/baselines/reference/underscoreTest1.symbols @@ -395,16 +395,10 @@ var buttonView = { onClick: function () { alert('clicked: ' + this.label); }, >onClick : Symbol(onClick, Decl(underscoreTest1_underscoreTests.ts, 97, 24)) >alert : Symbol(alert, Decl(underscoreTest1_underscoreTests.ts, 2, 14)) ->this.label : Symbol(label, Decl(underscoreTest1_underscoreTests.ts, 96, 18)) ->this : Symbol(buttonView, Decl(underscoreTest1_underscoreTests.ts, 96, 16)) ->label : Symbol(label, Decl(underscoreTest1_underscoreTests.ts, 96, 18)) onHover: function () { alert('hovering: ' + this.label); } >onHover : Symbol(onHover, Decl(underscoreTest1_underscoreTests.ts, 98, 62)) >alert : Symbol(alert, Decl(underscoreTest1_underscoreTests.ts, 2, 14)) ->this.label : Symbol(label, Decl(underscoreTest1_underscoreTests.ts, 96, 18)) ->this : Symbol(buttonView, Decl(underscoreTest1_underscoreTests.ts, 96, 16)) ->label : Symbol(label, Decl(underscoreTest1_underscoreTests.ts, 96, 18)) }; _.bindAll(buttonView); diff --git a/tests/baselines/reference/underscoreTest1.types b/tests/baselines/reference/underscoreTest1.types index 26e30ae6f52..afcc807b756 100644 --- a/tests/baselines/reference/underscoreTest1.types +++ b/tests/baselines/reference/underscoreTest1.types @@ -827,9 +827,9 @@ var buttonView = { >alert : (x: string) => void >'clicked: ' + this.label : string >'clicked: ' : "clicked: " ->this.label : string ->this : { label: string; onClick: () => void; onHover: () => void; } ->label : string +>this.label : any +>this : any +>label : any onHover: function () { alert('hovering: ' + this.label); } >onHover : () => void @@ -838,9 +838,9 @@ var buttonView = { >alert : (x: string) => void >'hovering: ' + this.label : string >'hovering: ' : "hovering: " ->this.label : string ->this : { label: string; onClick: () => void; onHover: () => void; } ->label : string +>this.label : any +>this : any +>label : any }; _.bindAll(buttonView); From 9d1b325e09f3f71071b213e819a8aa36b99b32e7 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 1 Mar 2017 06:31:34 -0800 Subject: [PATCH 29/65] Update another test --- .../reference/thisInObjectLiterals.errors.txt | 29 +++++++++++++++++++ .../reference/thisInObjectLiterals.js | 1 + .../thisKeyword/thisInObjectLiterals.ts | 3 ++ 3 files changed, 33 insertions(+) create mode 100644 tests/baselines/reference/thisInObjectLiterals.errors.txt diff --git a/tests/baselines/reference/thisInObjectLiterals.errors.txt b/tests/baselines/reference/thisInObjectLiterals.errors.txt new file mode 100644 index 00000000000..52ff6789559 --- /dev/null +++ b/tests/baselines/reference/thisInObjectLiterals.errors.txt @@ -0,0 +1,29 @@ +tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts(15,5): error TS7023: 'f' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions. +tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts(16,21): error TS2339: Property 'spaaace' does not exist on type '{ f(): any; }'. + + +==== tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts (2 errors) ==== + + class MyClass { + t: number; + + fn() { + type ContainingThis = this; + //type of 'this' in an object literal is the containing scope's this + var t = { x: this, y: this.t }; + var t: { x: ContainingThis; y: number }; + } + } + + //type of 'this' in an object literal method is the type of the object literal + var obj = { + f() { + ~ +!!! error TS7023: 'f' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions. + return this.spaaace; + ~~~~~~~ +!!! error TS2339: Property 'spaaace' does not exist on type '{ f(): any; }'. + } + }; + var obj: { f: () => any; }; + \ No newline at end of file diff --git a/tests/baselines/reference/thisInObjectLiterals.js b/tests/baselines/reference/thisInObjectLiterals.js index 6331f12105d..33a55cd5c71 100644 --- a/tests/baselines/reference/thisInObjectLiterals.js +++ b/tests/baselines/reference/thisInObjectLiterals.js @@ -1,4 +1,5 @@ //// [thisInObjectLiterals.ts] + class MyClass { t: number; diff --git a/tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts b/tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts index 6219586b6e5..7ba7d5b2e91 100644 --- a/tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts +++ b/tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts @@ -1,3 +1,6 @@ +// @noImplicitAny: true +// @noImplicitThis: true + class MyClass { t: number; From 0f50a5ffa747d8459b8f2078284fec083071dbb0 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Wed, 1 Mar 2017 08:29:33 -0800 Subject: [PATCH 30/65] Move code from 'Completions' to 'PathCompletions' namespace --- src/services/completions.ts | 562 +------------------------------- src/services/pathCompletions.ts | 538 ++++++++++++++++++++++++++++++ src/services/tsconfig.json | 1 + 3 files changed, 552 insertions(+), 549 deletions(-) create mode 100644 src/services/pathCompletions.ts diff --git a/src/services/completions.ts b/src/services/completions.ts index 1bf57d33fdc..08e78227989 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1,10 +1,12 @@ +/// + /* @internal */ namespace ts.Completions { export type Log = (message: string) => void; export function getCompletionsAtPosition(host: LanguageServiceHost, typeChecker: TypeChecker, log: Log, compilerOptions: CompilerOptions, sourceFile: SourceFile, position: number): CompletionInfo | undefined { if (isInReferenceComment(sourceFile, position)) { - return getTripleSlashReferenceCompletion(sourceFile, position, compilerOptions, host); + return PathCompletions.getTripleSlashReferenceCompletion(sourceFile, position, compilerOptions, host); } if (isInString(sourceFile, position)) { @@ -171,7 +173,7 @@ namespace ts.Completions { // i.e. import * as ns from "/*completion position*/"; // import x = require("/*completion position*/"); // var y = require("/*completion position*/"); - return getStringLiteralCompletionEntriesFromModuleNames(node, compilerOptions, host, typeChecker); + return PathCompletions.getStringLiteralCompletionEntriesFromModuleNames(node, compilerOptions, host, typeChecker); } else if (isEqualityExpression(node.parent)) { // Get completions from the type of the other operand @@ -273,489 +275,6 @@ namespace ts.Completions { } } - function getStringLiteralCompletionEntriesFromModuleNames(node: StringLiteral, compilerOptions: CompilerOptions, host: LanguageServiceHost, typeChecker: TypeChecker): CompletionInfo { - const literalValue = normalizeSlashes(node.text); - - const scriptPath = node.getSourceFile().path; - const scriptDirectory = getDirectoryPath(scriptPath); - - const span = getDirectoryFragmentTextSpan((node).text, node.getStart() + 1); - let entries: CompletionEntry[]; - if (isPathRelativeToScript(literalValue) || isRootedDiskPath(literalValue)) { - const extensions = getSupportedExtensions(compilerOptions); - if (compilerOptions.rootDirs) { - entries = getCompletionEntriesForDirectoryFragmentWithRootDirs( - compilerOptions.rootDirs, literalValue, scriptDirectory, extensions, /*includeExtensions*/false, span, compilerOptions, host, scriptPath); - } - else { - entries = getCompletionEntriesForDirectoryFragment( - literalValue, scriptDirectory, extensions, /*includeExtensions*/false, span, host, scriptPath); - } - } - else { - // Check for node modules - entries = getCompletionEntriesForNonRelativeModules(literalValue, scriptDirectory, span, compilerOptions, host, typeChecker); - } - return { - isGlobalCompletion: false, - isMemberCompletion: false, - isNewIdentifierLocation: true, - entries - }; - } - - /** - * Takes a script path and returns paths for all potential folders that could be merged with its - * containing folder via the "rootDirs" compiler option - */ - function getBaseDirectoriesFromRootDirs(rootDirs: string[], basePath: string, scriptPath: string, ignoreCase: boolean): string[] { - // Make all paths absolute/normalized if they are not already - rootDirs = map(rootDirs, rootDirectory => normalizePath(isRootedDiskPath(rootDirectory) ? rootDirectory : combinePaths(basePath, rootDirectory))); - - // Determine the path to the directory containing the script relative to the root directory it is contained within - let relativeDirectory: string; - for (const rootDirectory of rootDirs) { - if (containsPath(rootDirectory, scriptPath, basePath, ignoreCase)) { - relativeDirectory = scriptPath.substr(rootDirectory.length); - break; - } - } - - // Now find a path for each potential directory that is to be merged with the one containing the script - return deduplicate(map(rootDirs, rootDirectory => combinePaths(rootDirectory, relativeDirectory))); - } - - function getCompletionEntriesForDirectoryFragmentWithRootDirs(rootDirs: string[], fragment: string, scriptPath: string, extensions: string[], includeExtensions: boolean, span: TextSpan, compilerOptions: CompilerOptions, host: LanguageServiceHost, exclude?: string): CompletionEntry[] { - const basePath = compilerOptions.project || host.getCurrentDirectory(); - const ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames()); - const baseDirectories = getBaseDirectoriesFromRootDirs(rootDirs, basePath, scriptPath, ignoreCase); - - const result: CompletionEntry[] = []; - - for (const baseDirectory of baseDirectories) { - getCompletionEntriesForDirectoryFragment(fragment, baseDirectory, extensions, includeExtensions, span, host, exclude, result); - } - - return result; - } - - /** - * Given a path ending at a directory, gets the completions for the path, and filters for those entries containing the basename. - */ - function getCompletionEntriesForDirectoryFragment(fragment: string, scriptPath: string, extensions: string[], includeExtensions: boolean, span: TextSpan, host: LanguageServiceHost, exclude?: string, result: CompletionEntry[] = []): CompletionEntry[] { - if (fragment === undefined) { - fragment = ""; - } - - fragment = normalizeSlashes(fragment); - - /** - * Remove the basename from the path. Note that we don't use the basename to filter completions; - * the client is responsible for refining completions. - */ - fragment = getDirectoryPath(fragment); - - if (fragment === "") { - fragment = "." + directorySeparator; - } - - fragment = ensureTrailingDirectorySeparator(fragment); - - const absolutePath = normalizeAndPreserveTrailingSlash(isRootedDiskPath(fragment) ? fragment : combinePaths(scriptPath, fragment)); - const baseDirectory = getDirectoryPath(absolutePath); - const ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames()); - - if (tryDirectoryExists(host, baseDirectory)) { - // Enumerate the available files if possible - const files = tryReadDirectory(host, baseDirectory, extensions, /*exclude*/undefined, /*include*/["./*"]); - - if (files) { - /** - * Multiple file entries might map to the same truncated name once we remove extensions - * (happens iff includeExtensions === false)so we use a set-like data structure. Eg: - * - * both foo.ts and foo.tsx become foo - */ - const foundFiles = createMap(); - for (let filePath of files) { - filePath = normalizePath(filePath); - if (exclude && comparePaths(filePath, exclude, scriptPath, ignoreCase) === Comparison.EqualTo) { - continue; - } - - const foundFileName = includeExtensions ? getBaseFileName(filePath) : removeFileExtension(getBaseFileName(filePath)); - - if (!foundFiles.get(foundFileName)) { - foundFiles.set(foundFileName, true); - } - } - - forEachKey(foundFiles, foundFile => { - result.push(createCompletionEntryForModule(foundFile, ScriptElementKind.scriptElement, span)); - }); - } - - // If possible, get folder completion as well - const directories = tryGetDirectories(host, baseDirectory); - - if (directories) { - for (const directory of directories) { - const directoryName = getBaseFileName(normalizePath(directory)); - - result.push(createCompletionEntryForModule(directoryName, ScriptElementKind.directory, span)); - } - } - } - - return result; - } - - /** - * Check all of the declared modules and those in node modules. Possible sources of modules: - * Modules that are found by the type checker - * Modules found relative to "baseUrl" compliler options (including patterns from "paths" compiler option) - * Modules from node_modules (i.e. those listed in package.json) - * This includes all files that are found in node_modules/moduleName/ with acceptable file extensions - */ - function getCompletionEntriesForNonRelativeModules(fragment: string, scriptPath: string, span: TextSpan, compilerOptions: CompilerOptions, host: LanguageServiceHost, typeChecker: TypeChecker): CompletionEntry[] { - const { baseUrl, paths } = compilerOptions; - - let result: CompletionEntry[]; - - if (baseUrl) { - const fileExtensions = getSupportedExtensions(compilerOptions); - const projectDir = compilerOptions.project || host.getCurrentDirectory(); - const absolute = isRootedDiskPath(baseUrl) ? baseUrl : combinePaths(projectDir, baseUrl); - result = getCompletionEntriesForDirectoryFragment(fragment, normalizePath(absolute), fileExtensions, /*includeExtensions*/false, span, host); - - if (paths) { - for (const path in paths) { - if (paths.hasOwnProperty(path)) { - if (path === "*") { - if (paths[path]) { - for (const pattern of paths[path]) { - for (const match of getModulesForPathsPattern(fragment, baseUrl, pattern, fileExtensions, host)) { - result.push(createCompletionEntryForModule(match, ScriptElementKind.externalModuleName, span)); - } - } - } - } - else if (startsWith(path, fragment)) { - const entry = paths[path] && paths[path].length === 1 && paths[path][0]; - if (entry) { - result.push(createCompletionEntryForModule(path, ScriptElementKind.externalModuleName, span)); - } - } - } - } - } - } - else { - result = []; - } - - getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, span, result); - - for (const moduleName of enumeratePotentialNonRelativeModules(fragment, scriptPath, compilerOptions, typeChecker, host)) { - result.push(createCompletionEntryForModule(moduleName, ScriptElementKind.externalModuleName, span)); - } - - return result; - } - - function getModulesForPathsPattern(fragment: string, baseUrl: string, pattern: string, fileExtensions: string[], host: LanguageServiceHost): string[] { - if (host.readDirectory) { - const parsed = hasZeroOrOneAsteriskCharacter(pattern) ? tryParsePattern(pattern) : undefined; - if (parsed) { - // The prefix has two effective parts: the directory path and the base component after the filepath that is not a - // full directory component. For example: directory/path/of/prefix/base* - const normalizedPrefix = normalizeAndPreserveTrailingSlash(parsed.prefix); - const normalizedPrefixDirectory = getDirectoryPath(normalizedPrefix); - const normalizedPrefixBase = getBaseFileName(normalizedPrefix); - - const fragmentHasPath = fragment.indexOf(directorySeparator) !== -1; - - // Try and expand the prefix to include any path from the fragment so that we can limit the readDirectory call - const expandedPrefixDirectory = fragmentHasPath ? combinePaths(normalizedPrefixDirectory, normalizedPrefixBase + getDirectoryPath(fragment)) : normalizedPrefixDirectory; - - const normalizedSuffix = normalizePath(parsed.suffix); - const baseDirectory = combinePaths(baseUrl, expandedPrefixDirectory); - const completePrefix = fragmentHasPath ? baseDirectory : ensureTrailingDirectorySeparator(baseDirectory) + normalizedPrefixBase; - - // If we have a suffix, then we need to read the directory all the way down. We could create a glob - // that encodes the suffix, but we would have to escape the character "?" which readDirectory - // doesn't support. For now, this is safer but slower - const includeGlob = normalizedSuffix ? "**/*" : "./*"; - - const matches = tryReadDirectory(host, baseDirectory, fileExtensions, undefined, [includeGlob]); - if (matches) { - const result: string[] = []; - - // Trim away prefix and suffix - for (const match of matches) { - const normalizedMatch = normalizePath(match); - if (!endsWith(normalizedMatch, normalizedSuffix) || !startsWith(normalizedMatch, completePrefix)) { - continue; - } - - const start = completePrefix.length; - const length = normalizedMatch.length - start - normalizedSuffix.length; - - result.push(removeFileExtension(normalizedMatch.substr(start, length))); - } - return result; - } - } - } - - return undefined; - } - - function enumeratePotentialNonRelativeModules(fragment: string, scriptPath: string, options: CompilerOptions, typeChecker: TypeChecker, host: LanguageServiceHost): string[] { - // Check If this is a nested module - const isNestedModule = fragment.indexOf(directorySeparator) !== -1; - const moduleNameFragment = isNestedModule ? fragment.substr(0, fragment.lastIndexOf(directorySeparator)) : undefined; - - // Get modules that the type checker picked up - const ambientModules = map(typeChecker.getAmbientModules(), sym => stripQuotes(sym.name)); - let nonRelativeModules = filter(ambientModules, moduleName => startsWith(moduleName, fragment)); - - // Nested modules of the form "module-name/sub" need to be adjusted to only return the string - // after the last '/' that appears in the fragment because that's where the replacement span - // starts - if (isNestedModule) { - const moduleNameWithSeperator = ensureTrailingDirectorySeparator(moduleNameFragment); - nonRelativeModules = map(nonRelativeModules, moduleName => { - if (startsWith(fragment, moduleNameWithSeperator)) { - return moduleName.substr(moduleNameWithSeperator.length); - } - return moduleName; - }); - } - - - if (!options.moduleResolution || options.moduleResolution === ModuleResolutionKind.NodeJs) { - for (const visibleModule of enumerateNodeModulesVisibleToScript(host, scriptPath)) { - if (!isNestedModule) { - nonRelativeModules.push(visibleModule.moduleName); - } - else if (startsWith(visibleModule.moduleName, moduleNameFragment)) { - const nestedFiles = tryReadDirectory(host, visibleModule.moduleDir, supportedTypeScriptExtensions, /*exclude*/undefined, /*include*/["./*"]); - if (nestedFiles) { - for (let f of nestedFiles) { - f = normalizePath(f); - const nestedModule = removeFileExtension(getBaseFileName(f)); - nonRelativeModules.push(nestedModule); - } - } - } - } - } - - return deduplicate(nonRelativeModules); - } - - function getTripleSlashReferenceCompletion(sourceFile: SourceFile, position: number, compilerOptions: CompilerOptions, host: LanguageServiceHost): CompletionInfo { - const token = getTokenAtPosition(sourceFile, position); - if (!token) { - return undefined; - } - const commentRanges: CommentRange[] = getLeadingCommentRanges(sourceFile.text, token.pos); - - if (!commentRanges || !commentRanges.length) { - return undefined; - } - - const range = forEach(commentRanges, commentRange => position >= commentRange.pos && position <= commentRange.end && commentRange); - - if (!range) { - return undefined; - } - - const completionInfo: CompletionInfo = { - /** - * We don't want the editor to offer any other completions, such as snippets, inside a comment. - */ - isGlobalCompletion: false, - isMemberCompletion: false, - /** - * The user may type in a path that doesn't yet exist, creating a "new identifier" - * with respect to the collection of identifiers the server is aware of. - */ - isNewIdentifierLocation: true, - - entries: [] - }; - - const text = sourceFile.text.substr(range.pos, position - range.pos); - - const match = tripleSlashDirectiveFragmentRegex.exec(text); - - if (match) { - const prefix = match[1]; - const kind = match[2]; - const toComplete = match[3]; - - const scriptPath = getDirectoryPath(sourceFile.path); - if (kind === "path") { - // Give completions for a relative path - const span: TextSpan = getDirectoryFragmentTextSpan(toComplete, range.pos + prefix.length); - completionInfo.entries = getCompletionEntriesForDirectoryFragment(toComplete, scriptPath, getSupportedExtensions(compilerOptions), /*includeExtensions*/true, span, host, sourceFile.path); - } - else { - // Give completions based on the typings available - const span: TextSpan = { start: range.pos + prefix.length, length: match[0].length - prefix.length }; - completionInfo.entries = getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, span); - } - } - - return completionInfo; - } - - function getCompletionEntriesFromTypings(host: LanguageServiceHost, options: CompilerOptions, scriptPath: string, span: TextSpan, result: CompletionEntry[] = []): CompletionEntry[] { - // Check for typings specified in compiler options - if (options.types) { - for (const moduleName of options.types) { - result.push(createCompletionEntryForModule(moduleName, ScriptElementKind.externalModuleName, span)); - } - } - else if (host.getDirectories) { - let typeRoots: string[]; - try { - // Wrap in try catch because getEffectiveTypeRoots touches the filesystem - typeRoots = getEffectiveTypeRoots(options, host); - } - catch (e) {} - - if (typeRoots) { - for (const root of typeRoots) { - getCompletionEntriesFromDirectories(host, root, span, result); - } - } - } - - if (host.getDirectories) { - // Also get all @types typings installed in visible node_modules directories - for (const packageJson of findPackageJsons(scriptPath, host)) { - const typesDir = combinePaths(getDirectoryPath(packageJson), "node_modules/@types"); - getCompletionEntriesFromDirectories(host, typesDir, span, result); - } - } - - return result; - } - - function getCompletionEntriesFromDirectories(host: LanguageServiceHost, directory: string, span: TextSpan, result: Push) { - if (host.getDirectories && tryDirectoryExists(host, directory)) { - const directories = tryGetDirectories(host, directory); - if (directories) { - for (let typeDirectory of directories) { - typeDirectory = normalizePath(typeDirectory); - result.push(createCompletionEntryForModule(getBaseFileName(typeDirectory), ScriptElementKind.externalModuleName, span)); - } - } - } - } - - function findPackageJsons(currentDir: string, host: LanguageServiceHost): string[] { - const paths: string[] = []; - let currentConfigPath: string; - while (true) { - currentConfigPath = findConfigFile(currentDir, (f) => tryFileExists(host, f), "package.json"); - if (currentConfigPath) { - paths.push(currentConfigPath); - - currentDir = getDirectoryPath(currentConfigPath); - const parent = getDirectoryPath(currentDir); - if (currentDir === parent) { - break; - } - currentDir = parent; - } - else { - break; - } - } - - return paths; - } - - function enumerateNodeModulesVisibleToScript(host: LanguageServiceHost, scriptPath: string) { - const result: VisibleModuleInfo[] = []; - - if (host.readFile && host.fileExists) { - for (const packageJson of findPackageJsons(scriptPath, host)) { - const contents = tryReadingPackageJson(packageJson); - if (!contents) { - return; - } - - const nodeModulesDir = combinePaths(getDirectoryPath(packageJson), "node_modules"); - const foundModuleNames: string[] = []; - - // Provide completions for all non @types dependencies - for (const key of nodeModulesDependencyKeys) { - addPotentialPackageNames(contents[key], foundModuleNames); - } - - for (const moduleName of foundModuleNames) { - const moduleDir = combinePaths(nodeModulesDir, moduleName); - result.push({ - moduleName, - moduleDir - }); - } - } - } - - return result; - - function tryReadingPackageJson(filePath: string) { - try { - const fileText = tryReadFile(host, filePath); - return fileText ? JSON.parse(fileText) : undefined; - } - catch (e) { - return undefined; - } - } - - function addPotentialPackageNames(dependencies: any, result: string[]) { - if (dependencies) { - for (const dep in dependencies) { - if (dependencies.hasOwnProperty(dep) && !startsWith(dep, "@types/")) { - result.push(dep); - } - } - } - } - } - - function createCompletionEntryForModule(name: string, kind: string, replacementSpan: TextSpan): CompletionEntry { - return { name, kind, kindModifiers: ScriptElementKindModifier.none, sortText: name, replacementSpan }; - } - - // Replace everything after the last directory seperator that appears - function getDirectoryFragmentTextSpan(text: string, textStart: number): TextSpan { - const index = text.lastIndexOf(directorySeparator); - const offset = index !== -1 ? index + 1 : 0; - return { start: textStart + offset, length: text.length - offset }; - } - - // Returns true if the path is explicitly relative to the script (i.e. relative to . or ..) - function isPathRelativeToScript(path: string) { - if (path && path.length >= 2 && path.charCodeAt(0) === CharacterCodes.dot) { - const slashIndex = path.length >= 3 && path.charCodeAt(1) === CharacterCodes.dot ? 2 : 1; - const slashCharCode = path.charCodeAt(slashIndex); - return slashCharCode === CharacterCodes.slash || slashCharCode === CharacterCodes.backslash; - } - return false; - } - - function normalizeAndPreserveTrailingSlash(path: string) { - return hasTrailingDirectorySeparator(path) ? ensureTrailingDirectorySeparator(normalizePath(path)) : normalizePath(path); - } - export function getCompletionEntryDetails(typeChecker: TypeChecker, log: (message: string) => void, compilerOptions: CompilerOptions, sourceFile: SourceFile, position: number, entryName: string): CompletionEntryDetails { // Compute all the completion symbols again. const completionData = getCompletionData(typeChecker, log, sourceFile, position); @@ -1457,20 +976,18 @@ namespace ts.Completions { } function isFunction(kind: SyntaxKind): boolean { + if (!isFunctionLikeKind(kind)) { + return false; + } + switch (kind) { - case SyntaxKind.FunctionExpression: - case SyntaxKind.ArrowFunction: - case SyntaxKind.FunctionDeclaration: - case SyntaxKind.MethodDeclaration: - case SyntaxKind.MethodSignature: - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - case SyntaxKind.CallSignature: - case SyntaxKind.ConstructSignature: - case SyntaxKind.IndexSignature: + case SyntaxKind.Constructor: + case SyntaxKind.ConstructorType: + case SyntaxKind.FunctionType: + return false; + default: return true; } - return false; } /** @@ -1748,59 +1265,6 @@ namespace ts.Completions { }); } - /** - * Matches a triple slash reference directive with an incomplete string literal for its path. Used - * to determine if the caret is currently within the string literal and capture the literal fragment - * for completions. - * For example, this matches - * - * /// (host: LanguageServiceHost, toApply: (...a: any[]) => T, ...args: any[]) { - try { - return toApply && toApply.apply(host, args); - } - catch (e) {} - return undefined; - } - function isEqualityExpression(node: Node): node is BinaryExpression { return isBinaryExpression(node) && isEqualityOperatorKind(node.operatorToken.kind); } diff --git a/src/services/pathCompletions.ts b/src/services/pathCompletions.ts new file mode 100644 index 00000000000..96597da9d2d --- /dev/null +++ b/src/services/pathCompletions.ts @@ -0,0 +1,538 @@ +/* @internal */ +namespace ts.Completions.PathCompletions { + export function getStringLiteralCompletionEntriesFromModuleNames(node: StringLiteral, compilerOptions: CompilerOptions, host: LanguageServiceHost, typeChecker: TypeChecker): CompletionInfo { + const literalValue = normalizeSlashes(node.text); + + const scriptPath = node.getSourceFile().path; + const scriptDirectory = getDirectoryPath(scriptPath); + + const span = getDirectoryFragmentTextSpan((node).text, node.getStart() + 1); + let entries: CompletionEntry[]; + if (isPathRelativeToScript(literalValue) || isRootedDiskPath(literalValue)) { + const extensions = getSupportedExtensions(compilerOptions); + if (compilerOptions.rootDirs) { + entries = getCompletionEntriesForDirectoryFragmentWithRootDirs( + compilerOptions.rootDirs, literalValue, scriptDirectory, extensions, /*includeExtensions*/false, span, compilerOptions, host, scriptPath); + } + else { + entries = getCompletionEntriesForDirectoryFragment( + literalValue, scriptDirectory, extensions, /*includeExtensions*/false, span, host, scriptPath); + } + } + else { + // Check for node modules + entries = getCompletionEntriesForNonRelativeModules(literalValue, scriptDirectory, span, compilerOptions, host, typeChecker); + } + return { + isGlobalCompletion: false, + isMemberCompletion: false, + isNewIdentifierLocation: true, + entries + }; + } + + /** + * Takes a script path and returns paths for all potential folders that could be merged with its + * containing folder via the "rootDirs" compiler option + */ + function getBaseDirectoriesFromRootDirs(rootDirs: string[], basePath: string, scriptPath: string, ignoreCase: boolean): string[] { + // Make all paths absolute/normalized if they are not already + rootDirs = map(rootDirs, rootDirectory => normalizePath(isRootedDiskPath(rootDirectory) ? rootDirectory : combinePaths(basePath, rootDirectory))); + + // Determine the path to the directory containing the script relative to the root directory it is contained within + let relativeDirectory: string; + for (const rootDirectory of rootDirs) { + if (containsPath(rootDirectory, scriptPath, basePath, ignoreCase)) { + relativeDirectory = scriptPath.substr(rootDirectory.length); + break; + } + } + + // Now find a path for each potential directory that is to be merged with the one containing the script + return deduplicate(map(rootDirs, rootDirectory => combinePaths(rootDirectory, relativeDirectory))); + } + + function getCompletionEntriesForDirectoryFragmentWithRootDirs(rootDirs: string[], fragment: string, scriptPath: string, extensions: string[], includeExtensions: boolean, span: TextSpan, compilerOptions: CompilerOptions, host: LanguageServiceHost, exclude?: string): CompletionEntry[] { + const basePath = compilerOptions.project || host.getCurrentDirectory(); + const ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames()); + const baseDirectories = getBaseDirectoriesFromRootDirs(rootDirs, basePath, scriptPath, ignoreCase); + + const result: CompletionEntry[] = []; + + for (const baseDirectory of baseDirectories) { + getCompletionEntriesForDirectoryFragment(fragment, baseDirectory, extensions, includeExtensions, span, host, exclude, result); + } + + return result; + } + + /** + * Given a path ending at a directory, gets the completions for the path, and filters for those entries containing the basename. + */ + function getCompletionEntriesForDirectoryFragment(fragment: string, scriptPath: string, extensions: string[], includeExtensions: boolean, span: TextSpan, host: LanguageServiceHost, exclude?: string, result: CompletionEntry[] = []): CompletionEntry[] { + if (fragment === undefined) { + fragment = ""; + } + + fragment = normalizeSlashes(fragment); + + /** + * Remove the basename from the path. Note that we don't use the basename to filter completions; + * the client is responsible for refining completions. + */ + fragment = getDirectoryPath(fragment); + + if (fragment === "") { + fragment = "." + directorySeparator; + } + + fragment = ensureTrailingDirectorySeparator(fragment); + + const absolutePath = normalizeAndPreserveTrailingSlash(isRootedDiskPath(fragment) ? fragment : combinePaths(scriptPath, fragment)); + const baseDirectory = getDirectoryPath(absolutePath); + const ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames()); + + if (tryDirectoryExists(host, baseDirectory)) { + // Enumerate the available files if possible + const files = tryReadDirectory(host, baseDirectory, extensions, /*exclude*/undefined, /*include*/["./*"]); + + if (files) { + /** + * Multiple file entries might map to the same truncated name once we remove extensions + * (happens iff includeExtensions === false)so we use a set-like data structure. Eg: + * + * both foo.ts and foo.tsx become foo + */ + const foundFiles = createMap(); + for (let filePath of files) { + filePath = normalizePath(filePath); + if (exclude && comparePaths(filePath, exclude, scriptPath, ignoreCase) === Comparison.EqualTo) { + continue; + } + + const foundFileName = includeExtensions ? getBaseFileName(filePath) : removeFileExtension(getBaseFileName(filePath)); + + if (!foundFiles.get(foundFileName)) { + foundFiles.set(foundFileName, true); + } + } + + forEachKey(foundFiles, foundFile => { + result.push(createCompletionEntryForModule(foundFile, ScriptElementKind.scriptElement, span)); + }); + } + + // If possible, get folder completion as well + const directories = tryGetDirectories(host, baseDirectory); + + if (directories) { + for (const directory of directories) { + const directoryName = getBaseFileName(normalizePath(directory)); + + result.push(createCompletionEntryForModule(directoryName, ScriptElementKind.directory, span)); + } + } + } + + return result; + } + + /** + * Check all of the declared modules and those in node modules. Possible sources of modules: + * Modules that are found by the type checker + * Modules found relative to "baseUrl" compliler options (including patterns from "paths" compiler option) + * Modules from node_modules (i.e. those listed in package.json) + * This includes all files that are found in node_modules/moduleName/ with acceptable file extensions + */ + function getCompletionEntriesForNonRelativeModules(fragment: string, scriptPath: string, span: TextSpan, compilerOptions: CompilerOptions, host: LanguageServiceHost, typeChecker: TypeChecker): CompletionEntry[] { + const { baseUrl, paths } = compilerOptions; + + let result: CompletionEntry[]; + + if (baseUrl) { + const fileExtensions = getSupportedExtensions(compilerOptions); + const projectDir = compilerOptions.project || host.getCurrentDirectory(); + const absolute = isRootedDiskPath(baseUrl) ? baseUrl : combinePaths(projectDir, baseUrl); + result = getCompletionEntriesForDirectoryFragment(fragment, normalizePath(absolute), fileExtensions, /*includeExtensions*/false, span, host); + + if (paths) { + for (const path in paths) { + if (paths.hasOwnProperty(path)) { + if (path === "*") { + if (paths[path]) { + for (const pattern of paths[path]) { + for (const match of getModulesForPathsPattern(fragment, baseUrl, pattern, fileExtensions, host)) { + result.push(createCompletionEntryForModule(match, ScriptElementKind.externalModuleName, span)); + } + } + } + } + else if (startsWith(path, fragment)) { + const entry = paths[path] && paths[path].length === 1 && paths[path][0]; + if (entry) { + result.push(createCompletionEntryForModule(path, ScriptElementKind.externalModuleName, span)); + } + } + } + } + } + } + else { + result = []; + } + + getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, span, result); + + for (const moduleName of enumeratePotentialNonRelativeModules(fragment, scriptPath, compilerOptions, typeChecker, host)) { + result.push(createCompletionEntryForModule(moduleName, ScriptElementKind.externalModuleName, span)); + } + + return result; + } + + function getModulesForPathsPattern(fragment: string, baseUrl: string, pattern: string, fileExtensions: string[], host: LanguageServiceHost): string[] { + if (host.readDirectory) { + const parsed = hasZeroOrOneAsteriskCharacter(pattern) ? tryParsePattern(pattern) : undefined; + if (parsed) { + // The prefix has two effective parts: the directory path and the base component after the filepath that is not a + // full directory component. For example: directory/path/of/prefix/base* + const normalizedPrefix = normalizeAndPreserveTrailingSlash(parsed.prefix); + const normalizedPrefixDirectory = getDirectoryPath(normalizedPrefix); + const normalizedPrefixBase = getBaseFileName(normalizedPrefix); + + const fragmentHasPath = fragment.indexOf(directorySeparator) !== -1; + + // Try and expand the prefix to include any path from the fragment so that we can limit the readDirectory call + const expandedPrefixDirectory = fragmentHasPath ? combinePaths(normalizedPrefixDirectory, normalizedPrefixBase + getDirectoryPath(fragment)) : normalizedPrefixDirectory; + + const normalizedSuffix = normalizePath(parsed.suffix); + const baseDirectory = combinePaths(baseUrl, expandedPrefixDirectory); + const completePrefix = fragmentHasPath ? baseDirectory : ensureTrailingDirectorySeparator(baseDirectory) + normalizedPrefixBase; + + // If we have a suffix, then we need to read the directory all the way down. We could create a glob + // that encodes the suffix, but we would have to escape the character "?" which readDirectory + // doesn't support. For now, this is safer but slower + const includeGlob = normalizedSuffix ? "**/*" : "./*"; + + const matches = tryReadDirectory(host, baseDirectory, fileExtensions, undefined, [includeGlob]); + if (matches) { + const result: string[] = []; + + // Trim away prefix and suffix + for (const match of matches) { + const normalizedMatch = normalizePath(match); + if (!endsWith(normalizedMatch, normalizedSuffix) || !startsWith(normalizedMatch, completePrefix)) { + continue; + } + + const start = completePrefix.length; + const length = normalizedMatch.length - start - normalizedSuffix.length; + + result.push(removeFileExtension(normalizedMatch.substr(start, length))); + } + return result; + } + } + } + + return undefined; + } + + function enumeratePotentialNonRelativeModules(fragment: string, scriptPath: string, options: CompilerOptions, typeChecker: TypeChecker, host: LanguageServiceHost): string[] { + // Check If this is a nested module + const isNestedModule = fragment.indexOf(directorySeparator) !== -1; + const moduleNameFragment = isNestedModule ? fragment.substr(0, fragment.lastIndexOf(directorySeparator)) : undefined; + + // Get modules that the type checker picked up + const ambientModules = map(typeChecker.getAmbientModules(), sym => stripQuotes(sym.name)); + let nonRelativeModules = filter(ambientModules, moduleName => startsWith(moduleName, fragment)); + + // Nested modules of the form "module-name/sub" need to be adjusted to only return the string + // after the last '/' that appears in the fragment because that's where the replacement span + // starts + if (isNestedModule) { + const moduleNameWithSeperator = ensureTrailingDirectorySeparator(moduleNameFragment); + nonRelativeModules = map(nonRelativeModules, moduleName => { + if (startsWith(fragment, moduleNameWithSeperator)) { + return moduleName.substr(moduleNameWithSeperator.length); + } + return moduleName; + }); + } + + + if (!options.moduleResolution || options.moduleResolution === ModuleResolutionKind.NodeJs) { + for (const visibleModule of enumerateNodeModulesVisibleToScript(host, scriptPath)) { + if (!isNestedModule) { + nonRelativeModules.push(visibleModule.moduleName); + } + else if (startsWith(visibleModule.moduleName, moduleNameFragment)) { + const nestedFiles = tryReadDirectory(host, visibleModule.moduleDir, supportedTypeScriptExtensions, /*exclude*/undefined, /*include*/["./*"]); + if (nestedFiles) { + for (let f of nestedFiles) { + f = normalizePath(f); + const nestedModule = removeFileExtension(getBaseFileName(f)); + nonRelativeModules.push(nestedModule); + } + } + } + } + } + + return deduplicate(nonRelativeModules); + } + + export function getTripleSlashReferenceCompletion(sourceFile: SourceFile, position: number, compilerOptions: CompilerOptions, host: LanguageServiceHost): CompletionInfo { + const token = getTokenAtPosition(sourceFile, position); + if (!token) { + return undefined; + } + const commentRanges: CommentRange[] = getLeadingCommentRanges(sourceFile.text, token.pos); + + if (!commentRanges || !commentRanges.length) { + return undefined; + } + + const range = forEach(commentRanges, commentRange => position >= commentRange.pos && position <= commentRange.end && commentRange); + + if (!range) { + return undefined; + } + + const completionInfo: CompletionInfo = { + /** + * We don't want the editor to offer any other completions, such as snippets, inside a comment. + */ + isGlobalCompletion: false, + isMemberCompletion: false, + /** + * The user may type in a path that doesn't yet exist, creating a "new identifier" + * with respect to the collection of identifiers the server is aware of. + */ + isNewIdentifierLocation: true, + + entries: [] + }; + + const text = sourceFile.text.substr(range.pos, position - range.pos); + + const match = tripleSlashDirectiveFragmentRegex.exec(text); + + if (match) { + const prefix = match[1]; + const kind = match[2]; + const toComplete = match[3]; + + const scriptPath = getDirectoryPath(sourceFile.path); + if (kind === "path") { + // Give completions for a relative path + const span: TextSpan = getDirectoryFragmentTextSpan(toComplete, range.pos + prefix.length); + completionInfo.entries = getCompletionEntriesForDirectoryFragment(toComplete, scriptPath, getSupportedExtensions(compilerOptions), /*includeExtensions*/true, span, host, sourceFile.path); + } + else { + // Give completions based on the typings available + const span: TextSpan = { start: range.pos + prefix.length, length: match[0].length - prefix.length }; + completionInfo.entries = getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, span); + } + } + + return completionInfo; + } + + function getCompletionEntriesFromTypings(host: LanguageServiceHost, options: CompilerOptions, scriptPath: string, span: TextSpan, result: CompletionEntry[] = []): CompletionEntry[] { + // Check for typings specified in compiler options + if (options.types) { + for (const moduleName of options.types) { + result.push(createCompletionEntryForModule(moduleName, ScriptElementKind.externalModuleName, span)); + } + } + else if (host.getDirectories) { + let typeRoots: string[]; + try { + // Wrap in try catch because getEffectiveTypeRoots touches the filesystem + typeRoots = getEffectiveTypeRoots(options, host); + } + catch (e) {} + + if (typeRoots) { + for (const root of typeRoots) { + getCompletionEntriesFromDirectories(host, root, span, result); + } + } + } + + if (host.getDirectories) { + // Also get all @types typings installed in visible node_modules directories + for (const packageJson of findPackageJsons(scriptPath, host)) { + const typesDir = combinePaths(getDirectoryPath(packageJson), "node_modules/@types"); + getCompletionEntriesFromDirectories(host, typesDir, span, result); + } + } + + return result; + } + + function getCompletionEntriesFromDirectories(host: LanguageServiceHost, directory: string, span: TextSpan, result: Push) { + if (host.getDirectories && tryDirectoryExists(host, directory)) { + const directories = tryGetDirectories(host, directory); + if (directories) { + for (let typeDirectory of directories) { + typeDirectory = normalizePath(typeDirectory); + result.push(createCompletionEntryForModule(getBaseFileName(typeDirectory), ScriptElementKind.externalModuleName, span)); + } + } + } + } + + function findPackageJsons(currentDir: string, host: LanguageServiceHost): string[] { + const paths: string[] = []; + let currentConfigPath: string; + while (true) { + currentConfigPath = findConfigFile(currentDir, (f) => tryFileExists(host, f), "package.json"); + if (currentConfigPath) { + paths.push(currentConfigPath); + + currentDir = getDirectoryPath(currentConfigPath); + const parent = getDirectoryPath(currentDir); + if (currentDir === parent) { + break; + } + currentDir = parent; + } + else { + break; + } + } + + return paths; + } + + function enumerateNodeModulesVisibleToScript(host: LanguageServiceHost, scriptPath: string) { + const result: VisibleModuleInfo[] = []; + + if (host.readFile && host.fileExists) { + for (const packageJson of findPackageJsons(scriptPath, host)) { + const contents = tryReadingPackageJson(packageJson); + if (!contents) { + return; + } + + const nodeModulesDir = combinePaths(getDirectoryPath(packageJson), "node_modules"); + const foundModuleNames: string[] = []; + + // Provide completions for all non @types dependencies + for (const key of nodeModulesDependencyKeys) { + addPotentialPackageNames(contents[key], foundModuleNames); + } + + for (const moduleName of foundModuleNames) { + const moduleDir = combinePaths(nodeModulesDir, moduleName); + result.push({ + moduleName, + moduleDir + }); + } + } + } + + return result; + + function tryReadingPackageJson(filePath: string) { + try { + const fileText = tryReadFile(host, filePath); + return fileText ? JSON.parse(fileText) : undefined; + } + catch (e) { + return undefined; + } + } + + function addPotentialPackageNames(dependencies: any, result: string[]) { + if (dependencies) { + for (const dep in dependencies) { + if (dependencies.hasOwnProperty(dep) && !startsWith(dep, "@types/")) { + result.push(dep); + } + } + } + } + } + + function createCompletionEntryForModule(name: string, kind: string, replacementSpan: TextSpan): CompletionEntry { + return { name, kind, kindModifiers: ScriptElementKindModifier.none, sortText: name, replacementSpan }; + } + + // Replace everything after the last directory seperator that appears + function getDirectoryFragmentTextSpan(text: string, textStart: number): TextSpan { + const index = text.lastIndexOf(directorySeparator); + const offset = index !== -1 ? index + 1 : 0; + return { start: textStart + offset, length: text.length - offset }; + } + + // Returns true if the path is explicitly relative to the script (i.e. relative to . or ..) + function isPathRelativeToScript(path: string) { + if (path && path.length >= 2 && path.charCodeAt(0) === CharacterCodes.dot) { + const slashIndex = path.length >= 3 && path.charCodeAt(1) === CharacterCodes.dot ? 2 : 1; + const slashCharCode = path.charCodeAt(slashIndex); + return slashCharCode === CharacterCodes.slash || slashCharCode === CharacterCodes.backslash; + } + return false; + } + + function normalizeAndPreserveTrailingSlash(path: string) { + return hasTrailingDirectorySeparator(path) ? ensureTrailingDirectorySeparator(normalizePath(path)) : normalizePath(path); + } + + /** + * Matches a triple slash reference directive with an incomplete string literal for its path. Used + * to determine if the caret is currently within the string literal and capture the literal fragment + * for completions. + * For example, this matches + * + * /// (host: LanguageServiceHost, toApply: (...a: any[]) => T, ...args: any[]) { + try { + return toApply && toApply.apply(host, args); + } + catch (e) {} + return undefined; + } +} diff --git a/src/services/tsconfig.json b/src/services/tsconfig.json index ae2150d981d..93f861e80aa 100644 --- a/src/services/tsconfig.json +++ b/src/services/tsconfig.json @@ -53,6 +53,7 @@ "navigateTo.ts", "navigationBar.ts", "outliningElementsCollector.ts", + "pathCompletions.ts", "patternMatcher.ts", "preProcess.ts", "rename.ts", From 8371eb6401b9452d1ed7787001a876eb96b9b009 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Wed, 1 Mar 2017 09:28:51 -0800 Subject: [PATCH 31/65] Update tslint to `latest` (`next` is still on 4.3) and lint for BOM --- Jakefile.js | 3 +- package.json | 2 +- scripts/tslint/booleanTriviaRule.ts | 78 +++++++++++-------- scripts/tslint/nextLineRule.ts | 76 +++++++++--------- scripts/tslint/noBomRule.ts | 16 ++++ scripts/tslint/noInOperatorRule.ts | 13 ++-- scripts/tslint/noIncrementDecrementRule.ts | 59 ++++++++------ .../tslint/noTypeAssertionWhitespaceRule.ts | 12 +-- .../objectLiteralSurroundingSpaceRule.ts | 52 +++++++------ scripts/tslint/tsconfig.json | 5 ++ scripts/tslint/typeOperatorSpacingRule.ts | 38 ++++----- src/compiler/binder.ts | 2 +- src/compiler/checker.ts | 2 +- src/compiler/commandLineParser.ts | 2 +- src/compiler/core.ts | 2 +- src/compiler/emitter.ts | 2 +- src/compiler/factory.ts | 2 +- src/compiler/sys.ts | 2 +- src/compiler/transformer.ts | 2 +- src/compiler/transformers/generators.ts | 2 +- src/compiler/transformers/module/module.ts | 2 +- src/compiler/transformers/module/system.ts | 2 +- src/compiler/transformers/ts.ts | 2 +- src/compiler/tsc.ts | 2 +- src/compiler/types.ts | 2 +- src/compiler/utilities.ts | 2 +- src/compiler/visitor.ts | 2 +- src/harness/fourslash.ts | 2 +- .../unittests/cachingInServerLSHost.ts | 2 +- src/harness/unittests/initializeTSConfig.ts | 2 +- .../unittests/reuseProgramStructure.ts | 2 +- .../unittests/services/colorization.ts | 2 +- .../unittests/services/preProcessFile.ts | 2 +- src/harness/unittests/session.ts | 2 +- .../unittests/tsserverProjectSystem.ts | 2 +- src/harness/unittests/typingsInstaller.ts | 2 +- .../cancellationToken/cancellationToken.ts | 2 +- src/server/editorServices.ts | 2 +- src/server/project.ts | 2 +- src/server/session.ts | 2 +- .../typingsInstaller/nodeTypingsInstaller.ts | 2 +- .../typingsInstaller/typingsInstaller.ts | 2 +- src/services/codeFixProvider.ts | 2 +- src/services/codefixes/importFixes.ts | 2 +- .../codefixes/unusedIdentifierFixes.ts | 2 +- src/services/documentRegistry.ts | 2 +- src/services/findAllReferences.ts | 2 +- src/services/goToDefinition.ts | 2 +- src/services/jsDoc.ts | 2 +- src/services/jsTyping.ts | 2 +- src/services/navigateTo.ts | 2 +- src/services/services.ts | 2 +- src/services/transpile.ts | 2 +- src/services/utilities.ts | 2 +- tslint.json | 1 + 55 files changed, 247 insertions(+), 194 deletions(-) create mode 100644 scripts/tslint/noBomRule.ts diff --git a/Jakefile.js b/Jakefile.js index f8be7c2b671..17152285f2a 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -1098,7 +1098,8 @@ var tslintRules = [ "noInOperatorRule", "noIncrementDecrementRule", "objectLiteralSurroundingSpaceRule", - "noTypeAssertionWhitespaceRule" + "noTypeAssertionWhitespaceRule", + "noBomRule" ]; var tslintRulesFiles = tslintRules.map(function (p) { return path.join(tslintRuleDir, p + ".ts"); diff --git a/package.json b/package.json index 3ffab4bfb13..8b52eb6675e 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "through2": "latest", "travis-fold": "latest", "ts-node": "latest", - "tslint": "next", + "tslint": "latest", "typescript": "next" }, "scripts": { diff --git a/scripts/tslint/booleanTriviaRule.ts b/scripts/tslint/booleanTriviaRule.ts index db6abcbf17b..e79275c6392 100644 --- a/scripts/tslint/booleanTriviaRule.ts +++ b/scripts/tslint/booleanTriviaRule.ts @@ -2,52 +2,62 @@ import * as Lint from "tslint/lib"; import * as ts from "typescript"; export class Rule extends Lint.Rules.AbstractRule { - public static FAILURE_STRING_FACTORY = (name: string, currently: string) => `Tag boolean argument as '${name}' (currently '${currently}')`; + public static FAILURE_STRING_FACTORY(name: string, currently?: string): string { + const current = currently ? ` (currently '${currently}')` : ""; + return `Tag boolean argument as '${name}'${current}`; + } public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { + // Cheat to get type checker const program = ts.createProgram([sourceFile.fileName], Lint.createCompilerOptions()); const checker = program.getTypeChecker(); - return this.applyWithWalker(new BooleanTriviaWalker(checker, program.getSourceFile(sourceFile.fileName), this.getOptions())); + return this.applyWithFunction(program.getSourceFile(sourceFile.fileName), ctx => walk(ctx, checker)); } } -class BooleanTriviaWalker extends Lint.RuleWalker { - constructor(private checker: ts.TypeChecker, file: ts.SourceFile, opts: Lint.IOptions) { - super(file, opts); +function walk(ctx: Lint.WalkContext, checker: ts.TypeChecker): void { + ts.forEachChild(ctx.sourceFile, recur); + function recur(node: ts.Node): void { + if (node.kind === ts.SyntaxKind.CallExpression) { + checkCall(node as ts.CallExpression); + } + ts.forEachChild(node, recur); } - visitCallExpression(node: ts.CallExpression) { - super.visitCallExpression(node); - if (node.arguments && node.arguments.some(arg => arg.kind === ts.SyntaxKind.TrueKeyword || arg.kind === ts.SyntaxKind.FalseKeyword)) { - const targetCallSignature = this.checker.getResolvedSignature(node); - if (!!targetCallSignature) { - const targetParameters = targetCallSignature.getParameters(); - const source = this.getSourceFile(); - for (let index = 0; index < targetParameters.length; index++) { - const param = targetParameters[index]; - const arg = node.arguments[index]; - if (!(arg && param)) { - continue; - } + function checkCall(node: ts.CallExpression): void { + if (!node.arguments || !node.arguments.some(arg => arg.kind === ts.SyntaxKind.TrueKeyword || arg.kind === ts.SyntaxKind.FalseKeyword)) { + return; + } - const argType = this.checker.getContextualType(arg); - if (argType && (argType.getFlags() & ts.TypeFlags.Boolean)) { - if (arg.kind !== ts.SyntaxKind.TrueKeyword && arg.kind !== ts.SyntaxKind.FalseKeyword) { - continue; - } - let triviaContent: string; - const ranges = ts.getLeadingCommentRanges(arg.getFullText(), 0); - if (ranges && ranges.length === 1 && ranges[0].kind === ts.SyntaxKind.MultiLineCommentTrivia) { - triviaContent = arg.getFullText().slice(ranges[0].pos + 2, ranges[0].end - 2); // +/-2 to remove /**/ - } + const targetCallSignature = checker.getResolvedSignature(node); + if (!targetCallSignature) { + return; + } - const paramName = param.getName(); - if (triviaContent !== paramName && triviaContent !== paramName + ":") { - this.addFailure(this.createFailure(arg.getStart(source), arg.getWidth(source), Rule.FAILURE_STRING_FACTORY(param.getName(), triviaContent))); - } - } + const targetParameters = targetCallSignature.getParameters(); + for (let index = 0; index < targetParameters.length; index++) { + const param = targetParameters[index]; + const arg = node.arguments[index]; + if (!(arg && param)) { + continue; + } + + const argType = checker.getContextualType(arg); + if (argType && (argType.getFlags() & ts.TypeFlags.Boolean)) { + if (arg.kind !== ts.SyntaxKind.TrueKeyword && arg.kind !== ts.SyntaxKind.FalseKeyword) { + continue; + } + let triviaContent: string | undefined; + const ranges = ts.getLeadingCommentRanges(arg.getFullText(), 0); + if (ranges && ranges.length === 1 && ranges[0].kind === ts.SyntaxKind.MultiLineCommentTrivia) { + triviaContent = arg.getFullText().slice(ranges[0].pos + 2, ranges[0].end - 2); // +/-2 to remove /**/ + } + + const paramName = param.getName(); + if (triviaContent !== paramName && triviaContent !== paramName + ":") { + ctx.addFailureAtNode(arg, Rule.FAILURE_STRING_FACTORY(param.getName(), triviaContent)); } } } } -} +} \ No newline at end of file diff --git a/scripts/tslint/nextLineRule.ts b/scripts/tslint/nextLineRule.ts index 2dee393bd84..b149d09eb38 100644 --- a/scripts/tslint/nextLineRule.ts +++ b/scripts/tslint/nextLineRule.ts @@ -9,50 +9,56 @@ export class Rule extends Lint.Rules.AbstractRule { public static ELSE_FAILURE_STRING = "'else' should not be on the same line as the preceeding block's curly brace"; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - return this.applyWithWalker(new NextLineWalker(sourceFile, this.getOptions())); + const options = this.getOptions().ruleArguments; + const checkCatch = options.indexOf(OPTION_CATCH) !== -1; + const checkElse = options.indexOf(OPTION_ELSE) !== -1; + return this.applyWithFunction(sourceFile, ctx => walk(ctx, checkCatch, checkElse)); } } -class NextLineWalker extends Lint.RuleWalker { - public visitIfStatement(node: ts.IfStatement) { - const sourceFile = node.getSourceFile(); - const thenStatement = node.thenStatement; - - const elseStatement = node.elseStatement; - if (!!elseStatement) { - // find the else keyword - const elseKeyword = getFirstChildOfKind(node, ts.SyntaxKind.ElseKeyword); - if (this.hasOption(OPTION_ELSE) && !!elseKeyword) { - const thenStatementEndLoc = sourceFile.getLineAndCharacterOfPosition(thenStatement.getEnd()); - const elseKeywordLoc = sourceFile.getLineAndCharacterOfPosition(elseKeyword.getStart(sourceFile)); - if (thenStatementEndLoc.line === elseKeywordLoc.line) { - const failure = this.createFailure(elseKeyword.getStart(sourceFile), elseKeyword.getWidth(sourceFile), Rule.ELSE_FAILURE_STRING); - this.addFailure(failure); - } - } +function walk(ctx: Lint.WalkContext, checkCatch: boolean, checkElse: boolean): void { + const { sourceFile } = ctx; + function recur(node: ts.Node): void { + switch (node.kind) { + case ts.SyntaxKind.IfStatement: + checkIf(node as ts.IfStatement); + break; + case ts.SyntaxKind.TryStatement: + checkTry(node as ts.TryStatement); + break; } - - super.visitIfStatement(node); + ts.forEachChild(node, recur); } - public visitTryStatement(node: ts.TryStatement) { - const sourceFile = node.getSourceFile(); - const catchClause = node.catchClause; + function checkIf(node: ts.IfStatement): void { + const { thenStatement, elseStatement } = node; + if (!elseStatement) { + return; + } - // "visit" try block - const tryBlock = node.tryBlock; - - if (this.hasOption(OPTION_CATCH) && !!catchClause) { - const tryClosingBrace = tryBlock.getLastToken(sourceFile); - const catchKeyword = catchClause.getFirstToken(sourceFile); - const tryClosingBraceLoc = sourceFile.getLineAndCharacterOfPosition(tryClosingBrace.getEnd()); - const catchKeywordLoc = sourceFile.getLineAndCharacterOfPosition(catchKeyword.getStart(sourceFile)); - if (tryClosingBraceLoc.line === catchKeywordLoc.line) { - const failure = this.createFailure(catchKeyword.getStart(sourceFile), catchKeyword.getWidth(sourceFile), Rule.CATCH_FAILURE_STRING); - this.addFailure(failure); + // find the else keyword + const elseKeyword = getFirstChildOfKind(node, ts.SyntaxKind.ElseKeyword); + if (checkElse && !!elseKeyword) { + const thenStatementEndLoc = sourceFile.getLineAndCharacterOfPosition(thenStatement.getEnd()); + const elseKeywordLoc = sourceFile.getLineAndCharacterOfPosition(elseKeyword.getStart(sourceFile)); + if (thenStatementEndLoc.line === elseKeywordLoc.line) { + ctx.addFailureAtNode(elseKeyword, Rule.ELSE_FAILURE_STRING); } } - super.visitTryStatement(node); + } + + function checkTry({ tryBlock, catchClause }: ts.TryStatement): void { + if (!checkCatch || !catchClause) { + return; + } + + const tryClosingBrace = tryBlock.getLastToken(sourceFile); + const catchKeyword = catchClause.getFirstToken(sourceFile); + const tryClosingBraceLoc = sourceFile.getLineAndCharacterOfPosition(tryClosingBrace.getEnd()); + const catchKeywordLoc = sourceFile.getLineAndCharacterOfPosition(catchKeyword.getStart(sourceFile)); + if (tryClosingBraceLoc.line === catchKeywordLoc.line) { + ctx.addFailureAtNode(catchKeyword, Rule.CATCH_FAILURE_STRING); + } } } diff --git a/scripts/tslint/noBomRule.ts b/scripts/tslint/noBomRule.ts new file mode 100644 index 00000000000..105e2d2d68c --- /dev/null +++ b/scripts/tslint/noBomRule.ts @@ -0,0 +1,16 @@ +import * as Lint from "tslint/lib"; +import * as ts from "typescript"; + +export class Rule extends Lint.Rules.AbstractRule { + public static FAILURE_STRING = "This file has a BOM."; + + public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { + return this.applyWithFunction(sourceFile, walk); + } +} + +function walk(ctx: Lint.WalkContext): void { + if (ctx.sourceFile.text[0] === "\ufeff") { + ctx.addFailure(0, 1, Rule.FAILURE_STRING); + } +} diff --git a/scripts/tslint/noInOperatorRule.ts b/scripts/tslint/noInOperatorRule.ts index 307f0dffd6a..95f052ccaa6 100644 --- a/scripts/tslint/noInOperatorRule.ts +++ b/scripts/tslint/noInOperatorRule.ts @@ -1,20 +1,19 @@ import * as Lint from "tslint/lib"; import * as ts from "typescript"; - export class Rule extends Lint.Rules.AbstractRule { public static FAILURE_STRING = "Don't use the 'in' keyword - use 'hasProperty' to check for key presence instead"; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - return this.applyWithWalker(new InWalker(sourceFile, this.getOptions())); + return this.applyWithFunction(sourceFile, walk); } } -class InWalker extends Lint.RuleWalker { - visitNode(node: ts.Node) { - super.visitNode(node); - if (node.kind === ts.SyntaxKind.InKeyword && node.parent && node.parent.kind === ts.SyntaxKind.BinaryExpression) { - this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.FAILURE_STRING)); +function walk(ctx: Lint.WalkContext): void { + ts.forEachChild(ctx.sourceFile, recur); + function recur(node: ts.Node): void { + if (node.kind === ts.SyntaxKind.InKeyword && node.parent.kind === ts.SyntaxKind.BinaryExpression) { + ctx.addFailureAtNode(node, Rule.FAILURE_STRING); } } } diff --git a/scripts/tslint/noIncrementDecrementRule.ts b/scripts/tslint/noIncrementDecrementRule.ts index 2a957b36af5..ff2d81b1962 100644 --- a/scripts/tslint/noIncrementDecrementRule.ts +++ b/scripts/tslint/noIncrementDecrementRule.ts @@ -1,44 +1,55 @@ import * as Lint from "tslint/lib"; import * as ts from "typescript"; - export class Rule extends Lint.Rules.AbstractRule { public static POSTFIX_FAILURE_STRING = "Don't use '++' or '--' postfix operators outside statements or for loops."; public static PREFIX_FAILURE_STRING = "Don't use '++' or '--' prefix operators."; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - return this.applyWithWalker(new IncrementDecrementWalker(sourceFile, this.getOptions())); + return this.applyWithFunction(sourceFile, walk); } } -class IncrementDecrementWalker extends Lint.RuleWalker { +function walk(ctx: Lint.WalkContext): void { + ts.forEachChild(ctx.sourceFile, recur); + function recur(node: ts.Node): void { + switch (node.kind) { + case ts.SyntaxKind.PrefixUnaryExpression: + const { operator } = node as ts.PrefixUnaryExpression; + if (operator === ts.SyntaxKind.PlusPlusToken || operator === ts.SyntaxKind.MinusMinusToken) { + check(node as ts.PrefixUnaryExpression); + } + break; - visitPostfixUnaryExpression(node: ts.PostfixUnaryExpression) { - super.visitPostfixUnaryExpression(node); - if (node.operator === ts.SyntaxKind.PlusPlusToken || node.operator == ts.SyntaxKind.MinusMinusToken) { - this.visitIncrementDecrement(node); + case ts.SyntaxKind.PostfixUnaryExpression: + check(node as ts.PostfixUnaryExpression); + break; } } - visitPrefixUnaryExpression(node: ts.PrefixUnaryExpression) { - super.visitPrefixUnaryExpression(node); - if (node.operator === ts.SyntaxKind.PlusPlusToken || node.operator == ts.SyntaxKind.MinusMinusToken) { - this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.PREFIX_FAILURE_STRING)); + function check(node: ts.UnaryExpression): void { + if (!isAllowedLocation(node.parent!)) { + ctx.addFailureAtNode(node, Rule.POSTFIX_FAILURE_STRING); } } +} - visitIncrementDecrement(node: ts.UnaryExpression) { - if (node.parent && ( - // Can be a statement - node.parent.kind === ts.SyntaxKind.ExpressionStatement || - // Can be directly in a for-statement - node.parent.kind === ts.SyntaxKind.ForStatement || - // Can be in a comma operator in a for statement (`for (let a = 0, b = 10; a < b; a++, b--)`) - node.parent.kind === ts.SyntaxKind.BinaryExpression && - (node.parent).operatorToken.kind === ts.SyntaxKind.CommaToken && - node.parent.parent.kind === ts.SyntaxKind.ForStatement)) { - return; - } - this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.POSTFIX_FAILURE_STRING)); +function isAllowedLocation(node: ts.Node): boolean { + switch (node.kind) { + // Can be a statement + case ts.SyntaxKind.ExpressionStatement: + return true; + + // Can be directly in a for-statement + case ts.SyntaxKind.ForStatement: + return true; + + // Can be in a comma operator in a for statement (`for (let a = 0, b = 10; a < b; a++, b--)`) + case ts.SyntaxKind.BinaryExpression: + return (node as ts.BinaryExpression).operatorToken.kind === ts.SyntaxKind.CommaToken && + node.parent!.kind === ts.SyntaxKind.ForStatement; + + default: + return false; } } diff --git a/scripts/tslint/noTypeAssertionWhitespaceRule.ts b/scripts/tslint/noTypeAssertionWhitespaceRule.ts index 5368dcf74ba..37017fb60e4 100644 --- a/scripts/tslint/noTypeAssertionWhitespaceRule.ts +++ b/scripts/tslint/noTypeAssertionWhitespaceRule.ts @@ -1,25 +1,25 @@ import * as Lint from "tslint/lib"; import * as ts from "typescript"; - export class Rule extends Lint.Rules.AbstractRule { public static TRAILING_FAILURE_STRING = "Excess trailing whitespace found around type assertion."; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - return this.applyWithWalker(new TypeAssertionWhitespaceWalker(sourceFile, this.getOptions())); + return this.applyWithFunction(sourceFile, walk); } } -class TypeAssertionWhitespaceWalker extends Lint.RuleWalker { - public visitNode(node: ts.Node) { +function walk(ctx: Lint.WalkContext): void { + ts.forEachChild(ctx.sourceFile, recur); + function recur(node: ts.Node) { if (node.kind === ts.SyntaxKind.TypeAssertionExpression) { const refined = node as ts.TypeAssertion; const leftSideWhitespaceStart = refined.type.getEnd() + 1; const rightSideWhitespaceEnd = refined.expression.getStart(); if (leftSideWhitespaceStart !== rightSideWhitespaceEnd) { - this.addFailure(this.createFailure(leftSideWhitespaceStart, rightSideWhitespaceEnd, Rule.TRAILING_FAILURE_STRING)); + ctx.addFailure(leftSideWhitespaceStart, rightSideWhitespaceEnd, Rule.TRAILING_FAILURE_STRING); } } - super.visitNode(node); + ts.forEachChild(node, recur); } } diff --git a/scripts/tslint/objectLiteralSurroundingSpaceRule.ts b/scripts/tslint/objectLiteralSurroundingSpaceRule.ts index a705e56c969..8546aa6c973 100644 --- a/scripts/tslint/objectLiteralSurroundingSpaceRule.ts +++ b/scripts/tslint/objectLiteralSurroundingSpaceRule.ts @@ -1,7 +1,6 @@ import * as Lint from "tslint/lib"; import * as ts from "typescript"; - export class Rule extends Lint.Rules.AbstractRule { public static LEADING_FAILURE_STRING = "No leading whitespace found on single-line object literal."; public static TRAILING_FAILURE_STRING = "No trailing whitespace found on single-line object literal."; @@ -9,34 +8,37 @@ export class Rule extends Lint.Rules.AbstractRule { public static TRAILING_EXCESS_FAILURE_STRING = "Excess trailing whitespace found on single-line object literal."; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - return this.applyWithWalker(new ObjectLiteralSpaceWalker(sourceFile, this.getOptions())); + return this.applyWithFunction(sourceFile, walk); } } -class ObjectLiteralSpaceWalker extends Lint.RuleWalker { - public visitNode(node: ts.Node) { +function walk(ctx: Lint.WalkContext): void { + const { sourceFile } = ctx; + ts.forEachChild(sourceFile, recur); + function recur(node: ts.Node): void { if (node.kind === ts.SyntaxKind.ObjectLiteralExpression) { - const literal = node as ts.ObjectLiteralExpression; - const text = literal.getText(); - if (text.match(/^{[^\n]+}$/g)) { - if (text.charAt(1) !== " ") { - const failure = this.createFailure(node.pos, node.getWidth(), Rule.LEADING_FAILURE_STRING); - this.addFailure(failure); - } - if (text.charAt(2) === " ") { - const failure = this.createFailure(node.pos + 2, 1, Rule.LEADING_EXCESS_FAILURE_STRING); - this.addFailure(failure); - } - if (text.charAt(text.length - 2) !== " ") { - const failure = this.createFailure(node.pos, node.getWidth(), Rule.TRAILING_FAILURE_STRING); - this.addFailure(failure); - } - if (text.charAt(text.length - 3) === " ") { - const failure = this.createFailure(node.pos + node.getWidth() - 3, 1, Rule.TRAILING_EXCESS_FAILURE_STRING); - this.addFailure(failure); - } - } + check(node as ts.ObjectLiteralExpression); + } + ts.forEachChild(node, recur); + } + + function check(node: ts.ObjectLiteralExpression): void { + const text = node.getText(sourceFile); + if (!text.match(/^{[^\n]+}$/g)) { + return; + } + + if (text.charAt(1) !== " ") { + ctx.addFailureAtNode(node, Rule.LEADING_FAILURE_STRING); + } + if (text.charAt(2) === " ") { + ctx.addFailureAt(node.pos + 2, 1, Rule.LEADING_EXCESS_FAILURE_STRING); + } + if (text.charAt(text.length - 2) !== " ") { + ctx.addFailureAtNode(node, Rule.TRAILING_FAILURE_STRING); + } + if (text.charAt(text.length - 3) === " ") { + ctx.addFailureAt(node.pos + node.getWidth() - 3, 1, Rule.TRAILING_EXCESS_FAILURE_STRING); } - super.visitNode(node); } } diff --git a/scripts/tslint/tsconfig.json b/scripts/tslint/tsconfig.json index db018ce2776..c9bf8dc01dc 100644 --- a/scripts/tslint/tsconfig.json +++ b/scripts/tslint/tsconfig.json @@ -1,6 +1,11 @@ { "compilerOptions": { "noImplicitAny": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "strictNullChecks": true, "module": "commonjs", "outDir": "../../built/local/tslint" } diff --git a/scripts/tslint/typeOperatorSpacingRule.ts b/scripts/tslint/typeOperatorSpacingRule.ts index 50f2971a0ee..4bd70e6eefa 100644 --- a/scripts/tslint/typeOperatorSpacingRule.ts +++ b/scripts/tslint/typeOperatorSpacingRule.ts @@ -1,34 +1,36 @@ import * as Lint from "tslint/lib"; import * as ts from "typescript"; - export class Rule extends Lint.Rules.AbstractRule { public static FAILURE_STRING = "The '|' and '&' operators must be surrounded by single spaces"; public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { - return this.applyWithWalker(new TypeOperatorSpacingWalker(sourceFile, this.getOptions())); + return this.applyWithFunction(sourceFile, walk); } } -class TypeOperatorSpacingWalker extends Lint.RuleWalker { - public visitNode(node: ts.Node) { +function walk(ctx: Lint.WalkContext): void { + const { sourceFile } = ctx; + ts.forEachChild(sourceFile, recur); + function recur(node: ts.Node): void { if (node.kind === ts.SyntaxKind.UnionType || node.kind === ts.SyntaxKind.IntersectionType) { - const types = (node).types; - let expectedStart = types[0].end + 2; // space, | or & - for (let i = 1; i < types.length; i++) { - const currentType = types[i]; - if (expectedStart !== currentType.pos || currentType.getLeadingTriviaWidth() !== 1) { - const sourceFile = currentType.getSourceFile(); - const previousTypeEndPos = sourceFile.getLineAndCharacterOfPosition(types[i - 1].end); - const currentTypeStartPos = sourceFile.getLineAndCharacterOfPosition(currentType.pos); - if (previousTypeEndPos.line === currentTypeStartPos.line) { - const failure = this.createFailure(currentType.pos, currentType.getWidth(), Rule.FAILURE_STRING); - this.addFailure(failure); - } + check((node as ts.UnionOrIntersectionTypeNode).types); + } + ts.forEachChild(node, recur); + } + + function check(types: ts.TypeNode[]): void { + let expectedStart = types[0].end + 2; // space, | or & + for (let i = 1; i < types.length; i++) { + const currentType = types[i]; + if (expectedStart !== currentType.pos || currentType.getLeadingTriviaWidth() !== 1) { + const previousTypeEndPos = sourceFile.getLineAndCharacterOfPosition(types[i - 1].end); + const currentTypeStartPos = sourceFile.getLineAndCharacterOfPosition(currentType.pos); + if (previousTypeEndPos.line === currentTypeStartPos.line) { + ctx.addFailureAtNode(currentType, Rule.FAILURE_STRING); } - expectedStart = currentType.end + 2; } + expectedStart = currentType.end + 2; } - super.visitNode(node); } } diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 7e8a99343bd..af322c53726 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1903,7 +1903,7 @@ namespace ts { // Even though in the AST the jsdoc @typedef node belongs to the current node, // its symbol might be in the same scope with the current node's symbol. Consider: - // + // // /** @typedef {string | number} MyType */ // function foo(); // diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 48baef4494c..8f2c32721f7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1,4 +1,4 @@ -/// +/// /// /* @internal */ diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 6b4e9ff590e..8631621ff7b 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -1,4 +1,4 @@ -/// +/// /// /// /// diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 71c0f55c9af..5550e2f62c2 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1,4 +1,4 @@ -/// +/// /// namespace ts { diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index ee224befd45..70557ea4374 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1,4 +1,4 @@ -/// +/// /// /// /// diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index cfafaabebff..3ff3bc2782f 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -1,4 +1,4 @@ -/// +/// /// namespace ts { diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index cf50ab6482b..2a15df80102 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -1,4 +1,4 @@ -/// +/// declare function setTimeout(handler: (...args: any[]) => void, timeout: number): any; declare function clearTimeout(handle: any): void; diff --git a/src/compiler/transformer.ts b/src/compiler/transformer.ts index b9a75015f41..df87b17955b 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -1,4 +1,4 @@ -/// +/// /// /// /// diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index 57e85f50f39..e55cfc76db3 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -1,4 +1,4 @@ -/// +/// /// // Transforms generator functions into a compatible ES5 representation with similar runtime diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index 72a3558b1a3..0240ddf38fe 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -1,4 +1,4 @@ -/// +/// /// /// diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts index 7488c51ed91..1a362c47fd1 100644 --- a/src/compiler/transformers/module/system.ts +++ b/src/compiler/transformers/module/system.ts @@ -1,4 +1,4 @@ -/// +/// /// /// diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index e712393b2f0..70e141d8559 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -1,4 +1,4 @@ -/// +/// /// /// diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index b1ffcff43a4..32b6a90e268 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -1,4 +1,4 @@ -/// +/// /// namespace ts { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index df851eb07df..142ab9767c4 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1,4 +1,4 @@ -namespace ts { +namespace ts { /** * Type of objects whose values are all of the same type. * The `in` and `for-in` operators can *not* be safely used, diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 2ab2fc2fc23..60d8d784d96 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1,4 +1,4 @@ -/// +/// /* @internal */ namespace ts { diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 2d75d646128..0f4a4ed6561 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -1,4 +1,4 @@ -/// +/// /// /// diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 49d1336c874..28c59d717c0 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1,4 +1,4 @@ -// +// // Copyright (c) Microsoft Corporation. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/harness/unittests/cachingInServerLSHost.ts b/src/harness/unittests/cachingInServerLSHost.ts index caeab18958e..5ea45d2a5f6 100644 --- a/src/harness/unittests/cachingInServerLSHost.ts +++ b/src/harness/unittests/cachingInServerLSHost.ts @@ -1,4 +1,4 @@ -/// +/// namespace ts { interface File { diff --git a/src/harness/unittests/initializeTSConfig.ts b/src/harness/unittests/initializeTSConfig.ts index cb995212a94..ab9aaea0001 100644 --- a/src/harness/unittests/initializeTSConfig.ts +++ b/src/harness/unittests/initializeTSConfig.ts @@ -1,4 +1,4 @@ -/// +/// /// namespace ts { diff --git a/src/harness/unittests/reuseProgramStructure.ts b/src/harness/unittests/reuseProgramStructure.ts index d13dd7a26fa..c9ecef0de44 100644 --- a/src/harness/unittests/reuseProgramStructure.ts +++ b/src/harness/unittests/reuseProgramStructure.ts @@ -1,4 +1,4 @@ -/// +/// /// namespace ts { diff --git a/src/harness/unittests/services/colorization.ts b/src/harness/unittests/services/colorization.ts index 70592ea4151..fd7d932885a 100644 --- a/src/harness/unittests/services/colorization.ts +++ b/src/harness/unittests/services/colorization.ts @@ -1,4 +1,4 @@ -/// +/// interface ClassificationEntry { value: any; diff --git a/src/harness/unittests/services/preProcessFile.ts b/src/harness/unittests/services/preProcessFile.ts index 403cccc8cf3..b7d319a690f 100644 --- a/src/harness/unittests/services/preProcessFile.ts +++ b/src/harness/unittests/services/preProcessFile.ts @@ -1,4 +1,4 @@ -/// +/// describe("PreProcessFile:", function () { function test(sourceText: string, readImportFile: boolean, detectJavaScriptImports: boolean, expectedPreProcess: ts.PreProcessedFileInfo): void { diff --git a/src/harness/unittests/session.ts b/src/harness/unittests/session.ts index 8d306a6099b..d3ea153e235 100644 --- a/src/harness/unittests/session.ts +++ b/src/harness/unittests/session.ts @@ -1,4 +1,4 @@ -/// +/// const expect: typeof _chai.expect = _chai.expect; diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 7446cc84deb..e356b52da6f 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -1,4 +1,4 @@ -/// +/// /// namespace ts.projectSystem { diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index 29076df80f2..7fa22c29c16 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -1,4 +1,4 @@ -/// +/// /// /// diff --git a/src/server/cancellationToken/cancellationToken.ts b/src/server/cancellationToken/cancellationToken.ts index 71a31d14016..0e7969c1e45 100644 --- a/src/server/cancellationToken/cancellationToken.ts +++ b/src/server/cancellationToken/cancellationToken.ts @@ -37,7 +37,7 @@ function createCancellationToken(args: string[]): ServerCancellationToken { // when client wants to signal cancellation it should create a named pipe with name= // server will synchronously check the presence of the pipe and treat its existance as indicator that current request should be canceled. // in case if client prefers to use more fine-grained schema than one name for all request it can add '*' to the end of cancelellationPipeName. - // in this case pipe name will be build dynamically as . + // in this case pipe name will be build dynamically as . if (cancellationPipeName.charAt(cancellationPipeName.length - 1) === "*") { const namePrefix = cancellationPipeName.slice(0, -1); if (namePrefix.length === 0 || namePrefix.indexOf("*") >= 0) { diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index d0535e2f528..d1bc57ee970 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1,4 +1,4 @@ -/// +/// /// /// /// diff --git a/src/server/project.ts b/src/server/project.ts index e4669ea191b..7125acb2c5f 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -1,4 +1,4 @@ -/// +/// /// /// /// diff --git a/src/server/session.ts b/src/server/session.ts index f1b373c4a90..f25fdb9c98f 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -226,7 +226,7 @@ namespace ts.server { /** * Represents operation that can schedule its next step to be executed later. - * Scheduling is done via instance of NextStep. If on current step subsequent step was not scheduled - operation is assumed to be completed. + * Scheduling is done via instance of NextStep. If on current step subsequent step was not scheduled - operation is assumed to be completed. */ class MultistepOperation { private requestId: number; diff --git a/src/server/typingsInstaller/nodeTypingsInstaller.ts b/src/server/typingsInstaller/nodeTypingsInstaller.ts index ff20e89e2d7..602a849b5cd 100644 --- a/src/server/typingsInstaller/nodeTypingsInstaller.ts +++ b/src/server/typingsInstaller/nodeTypingsInstaller.ts @@ -1,4 +1,4 @@ -/// +/// /// namespace ts.server.typingsInstaller { diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index e889f98789a..fa533450b26 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -1,4 +1,4 @@ -/// +/// /// /// /// diff --git a/src/services/codeFixProvider.ts b/src/services/codeFixProvider.ts index 10d0b8eef34..c22ba779d19 100644 --- a/src/services/codeFixProvider.ts +++ b/src/services/codeFixProvider.ts @@ -1,4 +1,4 @@ -/* @internal */ +/* @internal */ namespace ts { export interface CodeFix { errorCodes: number[]; diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index 1f1b499d03b..a5394c17cdd 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -1,4 +1,4 @@ -/* @internal */ +/* @internal */ namespace ts.codefix { type ImportCodeActionKind = "CodeChange" | "InsertingIntoExistingImport" | "NewImport"; diff --git a/src/services/codefixes/unusedIdentifierFixes.ts b/src/services/codefixes/unusedIdentifierFixes.ts index a45a3c26dba..61d48bdc3bc 100644 --- a/src/services/codefixes/unusedIdentifierFixes.ts +++ b/src/services/codefixes/unusedIdentifierFixes.ts @@ -1,4 +1,4 @@ -/* @internal */ +/* @internal */ namespace ts.codefix { registerCodeFix({ errorCodes: [ diff --git a/src/services/documentRegistry.ts b/src/services/documentRegistry.ts index 80b0133ccfe..e2cd20a4463 100644 --- a/src/services/documentRegistry.ts +++ b/src/services/documentRegistry.ts @@ -1,4 +1,4 @@ -namespace ts { +namespace ts { /** * The document registry represents a store of SourceFile objects that can be shared between * multiple LanguageService instances. A LanguageService instance holds on the SourceFile (AST) diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 24d7d648272..8576f48f6e3 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -1,4 +1,4 @@ -/* @internal */ +/* @internal */ namespace ts.FindAllReferences { export function findReferencedSymbols(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFiles: SourceFile[], sourceFile: SourceFile, position: number, findInStrings: boolean, findInComments: boolean, isForRename: boolean): ReferencedSymbol[] | undefined { const node = getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true); diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts index b732d8a1193..f2602903be3 100644 --- a/src/services/goToDefinition.ts +++ b/src/services/goToDefinition.ts @@ -1,4 +1,4 @@ -/* @internal */ +/* @internal */ namespace ts.GoToDefinition { export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile, position: number): DefinitionInfo[] { /// Triple slash reference comments diff --git a/src/services/jsDoc.ts b/src/services/jsDoc.ts index 08a51a63e63..de2481b8784 100644 --- a/src/services/jsDoc.ts +++ b/src/services/jsDoc.ts @@ -1,4 +1,4 @@ -/* @internal */ +/* @internal */ namespace ts.JsDoc { const jsDocTagNames = [ "augments", diff --git a/src/services/jsTyping.ts b/src/services/jsTyping.ts index 248ceef1bd3..e7196e8f491 100644 --- a/src/services/jsTyping.ts +++ b/src/services/jsTyping.ts @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0. +// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0. // See LICENSE.txt in the project root for complete license information. /// diff --git a/src/services/navigateTo.ts b/src/services/navigateTo.ts index 05ccbcc71f4..2c8d43b535b 100644 --- a/src/services/navigateTo.ts +++ b/src/services/navigateTo.ts @@ -1,4 +1,4 @@ -/* @internal */ +/* @internal */ namespace ts.NavigateTo { type RawNavigateToItem = { name: string; fileName: string; matchKind: PatternMatchKind; isCaseSensitive: boolean; declaration: Declaration }; diff --git a/src/services/services.ts b/src/services/services.ts index f122e39bcc6..df5330ebaed 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1,4 +1,4 @@ -/// +/// /// /// diff --git a/src/services/transpile.ts b/src/services/transpile.ts index 86c6a3e8904..89ddb887809 100644 --- a/src/services/transpile.ts +++ b/src/services/transpile.ts @@ -1,4 +1,4 @@ -namespace ts { +namespace ts { export interface TranspileOptions { compilerOptions?: CompilerOptions; fileName?: string; diff --git a/src/services/utilities.ts b/src/services/utilities.ts index a4f574b9c28..7c5bf862fc8 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1,4 +1,4 @@ -// These utilities are common to multiple language service features. +// These utilities are common to multiple language service features. /* @internal */ namespace ts { export const scanner: Scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true); diff --git a/tslint.json b/tslint.json index 13de7acec63..37f64a05159 100644 --- a/tslint.json +++ b/tslint.json @@ -1,5 +1,6 @@ { "rules": { + "no-bom": true, "class-name": true, "comment-format": [true, "check-space" From 7561cdf6bf3b9187f6fdfc704f8f867615fd1d59 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 1 Mar 2017 17:16:09 -0800 Subject: [PATCH 32/65] Add ThisType to Object.{create|defineProperty|defineProperties} --- src/lib/es5.d.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index 711981888a9..04743f7d77f 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -147,7 +147,7 @@ interface ObjectConstructor { * @param o Object to use as a prototype. May be null * @param properties JavaScript object that contains one or more property descriptors. */ - create(o: object | null, properties: PropertyDescriptorMap): any; + create(o: object | null, properties: PropertyDescriptorMap & ThisType): any; /** * Adds a property to an object, or modifies attributes of an existing property. @@ -155,14 +155,14 @@ interface ObjectConstructor { * @param p The property name. * @param attributes Descriptor for the property. It can be for a data property or an accessor property. */ - defineProperty(o: any, p: string, attributes: PropertyDescriptor): any; + defineProperty(o: any, p: string, attributes: PropertyDescriptor & ThisType): any; /** * Adds one or more properties to an object, and/or modifies attributes of existing properties. * @param o Object on which to add or modify the properties. This can be a native JavaScript object or a DOM object. * @param properties JavaScript object that contains one or more descriptor objects. Each descriptor object describes a data property or an accessor property. */ - defineProperties(o: any, properties: PropertyDescriptorMap): any; + defineProperties(o: any, properties: PropertyDescriptorMap & ThisType): any; /** * Prevents the modification of attributes of existing properties, and prevents the addition of new properties. From 258bb4ff55f0336ac4df67056296eca23eaf783b Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 1 Mar 2017 17:16:35 -0800 Subject: [PATCH 33/65] Accept new baselines --- .../reference/getterSetterNonAccessor.types | 4 +- tests/baselines/reference/objectCreate.types | 40 +++++++++---------- tests/baselines/reference/objectCreate2.types | 40 +++++++++---------- .../reference/objectLitGetterSetter.types | 4 +- 4 files changed, 44 insertions(+), 44 deletions(-) diff --git a/tests/baselines/reference/getterSetterNonAccessor.types b/tests/baselines/reference/getterSetterNonAccessor.types index f5eb22296f3..4fbff67ee49 100644 --- a/tests/baselines/reference/getterSetterNonAccessor.types +++ b/tests/baselines/reference/getterSetterNonAccessor.types @@ -9,9 +9,9 @@ function setFunc(v){} Object.defineProperty({}, "0", ({ >Object.defineProperty({}, "0", ({ get: getFunc, set: setFunc, configurable: true })) : any ->Object.defineProperty : (o: any, p: string, attributes: PropertyDescriptor) => any +>Object.defineProperty : (o: any, p: string, attributes: PropertyDescriptor & ThisType) => any >Object : ObjectConstructor ->defineProperty : (o: any, p: string, attributes: PropertyDescriptor) => any +>defineProperty : (o: any, p: string, attributes: PropertyDescriptor & ThisType) => any >{} : {} >"0" : "0" >({ get: getFunc, set: setFunc, configurable: true }) : PropertyDescriptor diff --git a/tests/baselines/reference/objectCreate.types b/tests/baselines/reference/objectCreate.types index b4e0e72061e..8bf433e53fe 100644 --- a/tests/baselines/reference/objectCreate.types +++ b/tests/baselines/reference/objectCreate.types @@ -9,17 +9,17 @@ declare var union: null | { a: number, b: string }; var n = Object.create(null); // object >n : any >Object.create(null) : any ->Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; } +>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType): any; } >Object : ObjectConstructor ->create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; } +>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType): any; } >null : null var t = Object.create({ a: 1, b: "" }); // {a: number, b: string } >t : any >Object.create({ a: 1, b: "" }) : any ->Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; } +>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType): any; } >Object : ObjectConstructor ->create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; } +>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType): any; } >{ a: 1, b: "" } : { a: number; b: string; } >a : number >1 : 1 @@ -29,43 +29,43 @@ var t = Object.create({ a: 1, b: "" }); // {a: number, b: string } var u = Object.create(union); // object | {a: number, b: string } >u : any >Object.create(union) : any ->Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; } +>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType): any; } >Object : ObjectConstructor ->create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; } +>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType): any; } >union : { a: number; b: string; } | null var e = Object.create({}); // {} >e : any >Object.create({}) : any ->Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; } +>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType): any; } >Object : ObjectConstructor ->create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; } +>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType): any; } >{} : {} var o = Object.create({}); // object >o : any >Object.create({}) : any ->Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; } +>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType): any; } >Object : ObjectConstructor ->create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; } +>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType): any; } >{} : object >{} : {} var a = Object.create(null, {}); // any >a : any >Object.create(null, {}) : any ->Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; } +>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType): any; } >Object : ObjectConstructor ->create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; } +>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType): any; } >null : null >{} : {} var a = Object.create({ a: 1, b: "" }, {}); >a : any >Object.create({ a: 1, b: "" }, {}) : any ->Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; } +>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType): any; } >Object : ObjectConstructor ->create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; } +>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType): any; } >{ a: 1, b: "" } : { a: number; b: string; } >a : number >1 : 1 @@ -76,27 +76,27 @@ var a = Object.create({ a: 1, b: "" }, {}); var a = Object.create(union, {}); >a : any >Object.create(union, {}) : any ->Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; } +>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType): any; } >Object : ObjectConstructor ->create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; } +>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType): any; } >union : { a: number; b: string; } | null >{} : {} var a = Object.create({}, {}); >a : any >Object.create({}, {}) : any ->Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; } +>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType): any; } >Object : ObjectConstructor ->create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; } +>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType): any; } >{} : {} >{} : {} var a = Object.create({}, {}); >a : any >Object.create({}, {}) : any ->Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; } +>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType): any; } >Object : ObjectConstructor ->create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; } +>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType): any; } >{} : object >{} : {} >{} : {} diff --git a/tests/baselines/reference/objectCreate2.types b/tests/baselines/reference/objectCreate2.types index 3e19c08bfc0..1602d70d571 100644 --- a/tests/baselines/reference/objectCreate2.types +++ b/tests/baselines/reference/objectCreate2.types @@ -9,17 +9,17 @@ declare var union: null | { a: number, b: string }; var n = Object.create(null); // any >n : any >Object.create(null) : any ->Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; } +>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType): any; } >Object : ObjectConstructor ->create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; } +>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType): any; } >null : null var t = Object.create({ a: 1, b: "" }); // {a: number, b: string } >t : any >Object.create({ a: 1, b: "" }) : any ->Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; } +>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType): any; } >Object : ObjectConstructor ->create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; } +>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType): any; } >{ a: 1, b: "" } : { a: number; b: string; } >a : number >1 : 1 @@ -29,43 +29,43 @@ var t = Object.create({ a: 1, b: "" }); // {a: number, b: string } var u = Object.create(union); // {a: number, b: string } >u : any >Object.create(union) : any ->Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; } +>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType): any; } >Object : ObjectConstructor ->create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; } +>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType): any; } >union : { a: number; b: string; } var e = Object.create({}); // {} >e : any >Object.create({}) : any ->Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; } +>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType): any; } >Object : ObjectConstructor ->create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; } +>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType): any; } >{} : {} var o = Object.create({}); // object >o : any >Object.create({}) : any ->Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; } +>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType): any; } >Object : ObjectConstructor ->create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; } +>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType): any; } >{} : object >{} : {} var a = Object.create(null, {}); // any >a : any >Object.create(null, {}) : any ->Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; } +>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType): any; } >Object : ObjectConstructor ->create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; } +>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType): any; } >null : null >{} : {} var a = Object.create({ a: 1, b: "" }, {}); >a : any >Object.create({ a: 1, b: "" }, {}) : any ->Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; } +>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType): any; } >Object : ObjectConstructor ->create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; } +>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType): any; } >{ a: 1, b: "" } : { a: number; b: string; } >a : number >1 : 1 @@ -76,27 +76,27 @@ var a = Object.create({ a: 1, b: "" }, {}); var a = Object.create(union, {}); >a : any >Object.create(union, {}) : any ->Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; } +>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType): any; } >Object : ObjectConstructor ->create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; } +>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType): any; } >union : { a: number; b: string; } >{} : {} var a = Object.create({}, {}); >a : any >Object.create({}, {}) : any ->Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; } +>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType): any; } >Object : ObjectConstructor ->create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; } +>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType): any; } >{} : {} >{} : {} var a = Object.create({}, {}); >a : any >Object.create({}, {}) : any ->Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; } +>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType): any; } >Object : ObjectConstructor ->create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; } +>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType): any; } >{} : object >{} : {} >{} : {} diff --git a/tests/baselines/reference/objectLitGetterSetter.types b/tests/baselines/reference/objectLitGetterSetter.types index 12801b65340..c2ce173e029 100644 --- a/tests/baselines/reference/objectLitGetterSetter.types +++ b/tests/baselines/reference/objectLitGetterSetter.types @@ -5,9 +5,9 @@ Object.defineProperty(obj, "accProperty", ({ >Object.defineProperty(obj, "accProperty", ({ get: function () { eval("public = 1;"); return 11; }, set: function (v) { } })) : any ->Object.defineProperty : (o: any, p: string, attributes: PropertyDescriptor) => any +>Object.defineProperty : (o: any, p: string, attributes: PropertyDescriptor & ThisType) => any >Object : ObjectConstructor ->defineProperty : (o: any, p: string, attributes: PropertyDescriptor) => any +>defineProperty : (o: any, p: string, attributes: PropertyDescriptor & ThisType) => any >obj : {} >"accProperty" : "accProperty" >({ get: function () { eval("public = 1;"); return 11; }, set: function (v) { } }) : PropertyDescriptor From b2f7d4797762412e57e58798ad5ccadeac748e8e Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Fri, 3 Mar 2017 08:54:41 -0800 Subject: [PATCH 34/65] Remove old commented-out code --- tests/cases/fourslash/quickInfoDisplayPartsEnum1.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/cases/fourslash/quickInfoDisplayPartsEnum1.ts b/tests/cases/fourslash/quickInfoDisplayPartsEnum1.ts index 0bc3c1ab89b..14c7b3caf1c 100644 --- a/tests/cases/fourslash/quickInfoDisplayPartsEnum1.ts +++ b/tests/cases/fourslash/quickInfoDisplayPartsEnum1.ts @@ -19,6 +19,4 @@ /////*25*/eInstance1 = /*26*/constE./*27*/e2; /////*28*/eInstance1 = /*29*/constE./*30*/e3; -//goTo.marker("2"); -//verify.verifyQuickInfoDisplayParts("enum member", "", { start: 0, length: 2 }, /*displayParts*/[], /*documentation*/[]); verify.baselineQuickInfo(); From cda741d14a7e7339a361dc8d1aa8680533f80ebd Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 3 Mar 2017 10:25:10 -0800 Subject: [PATCH 35/65] Introduce --strict compiler option --- src/compiler/binder.ts | 2 +- src/compiler/checker.ts | 40 +++++++++++++++------------- src/compiler/commandLineParser.ts | 7 ++++- src/compiler/diagnosticMessages.json | 4 +++ src/compiler/program.ts | 2 +- src/compiler/transformers/ts.ts | 3 ++- src/compiler/types.ts | 9 ++++--- 7 files changed, 40 insertions(+), 27 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 7e8a99343bd..ef00a3aecde 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -182,7 +182,7 @@ namespace ts { return bindSourceFile; function bindInStrictMode(file: SourceFile, opts: CompilerOptions): boolean { - if (opts.alwaysStrict && !isDeclarationFile(file)) { + if ((opts.alwaysStrict === undefined ? opts.strict : opts.alwaysStrict) && !isDeclarationFile(file)) { // bind in strict mode source files with alwaysStrict option return true; } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9cd5b7a31d2..7b1a11e5300 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -56,7 +56,9 @@ namespace ts { const modulekind = getEmitModuleKind(compilerOptions); const noUnusedIdentifiers = !!compilerOptions.noUnusedLocals || !!compilerOptions.noUnusedParameters; const allowSyntheticDefaultImports = typeof compilerOptions.allowSyntheticDefaultImports !== "undefined" ? compilerOptions.allowSyntheticDefaultImports : modulekind === ModuleKind.System; - const strictNullChecks = compilerOptions.strictNullChecks; + const strictNullChecks = compilerOptions.strictNullChecks === undefined ? compilerOptions.strict : compilerOptions.strictNullChecks; + const noImplicitAny = compilerOptions.noImplicitAny === undefined ? compilerOptions.strict : compilerOptions.noImplicitAny; + const noImplicitThis = compilerOptions.noImplicitThis === undefined ? compilerOptions.strict : compilerOptions.noImplicitThis; const emitResolver = createResolver(); @@ -1564,7 +1566,7 @@ namespace ts { error(errorNode, diag, moduleReference, resolvedModule.resolvedFileName); return undefined; } - else if (compilerOptions.noImplicitAny && moduleNotFoundError) { + else if (noImplicitAny && moduleNotFoundError) { error(errorNode, Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type, moduleReference, @@ -3407,7 +3409,7 @@ namespace ts { return addOptionality(declaredType, /*optional*/ declaration.questionToken && includeOptionality); } - if ((compilerOptions.noImplicitAny || declaration.flags & NodeFlags.JavaScriptFile) && + if ((noImplicitAny || declaration.flags & NodeFlags.JavaScriptFile) && declaration.kind === SyntaxKind.VariableDeclaration && !isBindingPattern(declaration.name) && !(getCombinedModifierFlags(declaration) & ModifierFlags.Export) && !isInAmbientContext(declaration)) { // If --noImplicitAny is on or the declaration is in a Javascript file, @@ -3509,7 +3511,7 @@ namespace ts { if (isBindingPattern(element.name)) { return getTypeFromBindingPattern(element.name, includePatternInType, reportErrors); } - if (reportErrors && compilerOptions.noImplicitAny && !declarationBelongsToPrivateAmbientMember(element)) { + if (reportErrors && noImplicitAny && !declarationBelongsToPrivateAmbientMember(element)) { reportImplicitAnyError(element, anyType); } return anyType; @@ -3607,7 +3609,7 @@ namespace ts { type = declaration.dotDotDotToken ? anyArrayType : anyType; // Report implicit any errors unless this is a private property within an ambient declaration - if (reportErrors && compilerOptions.noImplicitAny) { + if (reportErrors && noImplicitAny) { if (!declarationBelongsToPrivateAmbientMember(declaration)) { reportImplicitAnyError(declaration, type); } @@ -3726,7 +3728,7 @@ namespace ts { } // Otherwise, fall back to 'any'. else { - if (compilerOptions.noImplicitAny) { + if (noImplicitAny) { if (setter) { error(setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation, symbolToString(symbol)); } @@ -3741,7 +3743,7 @@ namespace ts { } if (!popTypeResolution()) { type = anyType; - if (compilerOptions.noImplicitAny) { + if (noImplicitAny) { const getter = getDeclarationOfKind(symbol, SyntaxKind.GetAccessor); error(getter, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, symbolToString(symbol)); } @@ -3824,7 +3826,7 @@ namespace ts { return unknownType; } // Otherwise variable has initializer that circularly references the variable itself - if (compilerOptions.noImplicitAny) { + if (noImplicitAny) { error(symbol.valueDeclaration, Diagnostics._0_implicitly_has_type_any_because_it_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer, symbolToString(symbol)); } @@ -5585,7 +5587,7 @@ namespace ts { } if (!popTypeResolution()) { type = anyType; - if (compilerOptions.noImplicitAny) { + if (noImplicitAny) { const declaration = signature.declaration; if (declaration.name) { error(declaration.name, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, declarationNameToString(declaration.name)); @@ -6540,7 +6542,7 @@ namespace ts { return indexInfo.type; } if (accessExpression && !isConstEnumObjectType(objectType)) { - if (compilerOptions.noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors) { + if (noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors) { if (getIndexTypeOfType(objectType, IndexKind.Number)) { error(accessExpression.argumentExpression, Diagnostics.Element_implicitly_has_an_any_type_because_index_expression_is_not_of_type_number); } @@ -9126,7 +9128,7 @@ namespace ts { } function reportErrorsFromWidening(declaration: Declaration, type: Type) { - if (produceDiagnostics && compilerOptions.noImplicitAny && type.flags & TypeFlags.ContainsWideningType) { + if (produceDiagnostics && noImplicitAny && type.flags & TypeFlags.ContainsWideningType) { // Report implicit any error within type if possible, otherwise report error on declaration if (!reportWideningErrorsInType(type)) { reportImplicitAnyError(declaration, type); @@ -11007,7 +11009,7 @@ namespace ts { // control flow based type does include undefined. if (type === autoType || type === autoArrayType) { if (flowType === autoType || flowType === autoArrayType) { - if (compilerOptions.noImplicitAny) { + if (noImplicitAny) { error(declaration.name, Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined, symbolToString(symbol), typeToString(flowType)); error(node, Diagnostics.Variable_0_implicitly_has_an_1_type, symbolToString(symbol), typeToString(flowType)); } @@ -11277,7 +11279,7 @@ namespace ts { } } - if (compilerOptions.noImplicitThis) { + if (noImplicitThis) { // With noImplicitThis, functions may not reference 'this' if it has type 'any' error(node, Diagnostics.this_implicitly_has_type_any_because_it_does_not_have_a_type_annotation); } @@ -12531,7 +12533,7 @@ namespace ts { return links.resolvedSymbol = unknownSymbol; } else { - if (compilerOptions.noImplicitAny) { + if (noImplicitAny) { error(node, Diagnostics.JSX_element_implicitly_has_type_any_because_no_interface_JSX_0_exists, JsxNames.IntrinsicElements); } return links.resolvedSymbol = unknownSymbol; @@ -12919,7 +12921,7 @@ namespace ts { } if (jsxElementType === undefined) { - if (compilerOptions.noImplicitAny) { + if (noImplicitAny) { error(errorNode, Diagnostics.JSX_element_implicitly_has_type_any_because_the_global_type_JSX_Element_does_not_exist); } } @@ -14742,7 +14744,7 @@ namespace ts { if (funcSymbol && funcSymbol.members && funcSymbol.flags & SymbolFlags.Function) { return getInferredClassType(funcSymbol); } - else if (compilerOptions.noImplicitAny) { + else if (noImplicitAny) { error(node, Diagnostics.new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type); } return anyType; @@ -15002,7 +15004,7 @@ namespace ts { const iterableIteratorAny = functionFlags & FunctionFlags.Async ? createAsyncIterableIteratorType(anyType) // AsyncGenerator function : createIterableIteratorType(anyType); // Generator function - if (compilerOptions.noImplicitAny) { + if (noImplicitAny) { error(func.asteriskToken, Diagnostics.Generator_implicitly_has_type_0_because_it_does_not_yield_any_values_Consider_supplying_a_return_type, typeToString(iterableIteratorAny)); } @@ -16544,7 +16546,7 @@ namespace ts { if (produceDiagnostics) { checkCollisionWithArgumentsInGeneratedCode(node); - if (compilerOptions.noImplicitAny && !node.type) { + if (noImplicitAny && !node.type) { switch (node.kind) { case SyntaxKind.ConstructSignature: error(node, Diagnostics.Construct_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type); @@ -17856,7 +17858,7 @@ namespace ts { if (produceDiagnostics && !node.type) { // Report an implicit any error if there is no body, no explicit return type, and node is not a private method // in an ambient context - if (compilerOptions.noImplicitAny && nodeIsMissing(node.body) && !isPrivateWithinAmbient(node)) { + if (noImplicitAny && nodeIsMissing(node.body) && !isPrivateWithinAmbient(node)) { reportImplicitAnyError(node, anyType); } diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 6b4e9ff590e..17bbbcb8a56 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -467,6 +467,11 @@ namespace ts { type: "boolean", description: Diagnostics.Parse_in_strict_mode_and_emit_use_strict_for_each_source_file }, + { + name: "strict", + type: "boolean", + description: Diagnostics.Enable_all_strict_type_checks + }, { // A list of plugins to load in the language service name: "plugins", @@ -520,7 +525,7 @@ namespace ts { export const defaultInitCompilerOptions: CompilerOptions = { module: ModuleKind.CommonJS, target: ScriptTarget.ES5, - noImplicitAny: false, + strict: false, sourceMap: false, }; diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 75aa5d25f72..318f06ceeaa 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3045,6 +3045,10 @@ "category": "Message", "code": 6149 }, + "Enable all strict type checks.": { + "category": "Message", + "code": 6150 + }, "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", "code": 7005 diff --git a/src/compiler/program.ts b/src/compiler/program.ts index eb9f0f0e0a1..d9ddf486e0d 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1630,7 +1630,7 @@ namespace ts { programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "lib", "noLib")); } - if (options.noImplicitUseStrict && options.alwaysStrict) { + if (options.noImplicitUseStrict && (options.alwaysStrict === undefined ? options.strict : options.alwaysStrict)) { programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "noImplicitUseStrict", "alwaysStrict")); } diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index e712393b2f0..b3696c31153 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -472,7 +472,8 @@ namespace ts { } function visitSourceFile(node: SourceFile) { - const alwaysStrict = compilerOptions.alwaysStrict && !(isExternalModule(node) && moduleKind === ModuleKind.ES2015); + const alwaysStrict = (compilerOptions.alwaysStrict === undefined ? compilerOptions.strict : compilerOptions.alwaysStrict) && + !(isExternalModule(node) && moduleKind === ModuleKind.ES2015); return updateSourceFileNode( node, visitLexicalEnvironment(node.statements, sourceElementVisitor, context, /*start*/ 0, alwaysStrict)); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 4ffd44e6aa1..d9134cca091 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3308,7 +3308,7 @@ allowSyntheticDefaultImports?: boolean; allowUnreachableCode?: boolean; allowUnusedLabels?: boolean; - alwaysStrict?: boolean; + alwaysStrict?: boolean; // Always combine with strict property baseUrl?: string; charset?: string; /* @internal */ configFilePath?: string; @@ -3344,9 +3344,9 @@ noEmitOnError?: boolean; noErrorTruncation?: boolean; noFallthroughCasesInSwitch?: boolean; - noImplicitAny?: boolean; + noImplicitAny?: boolean; // Always combine with strict property noImplicitReturns?: boolean; - noImplicitThis?: boolean; + noImplicitThis?: boolean; // Always combine with strict property noUnusedLocals?: boolean; noUnusedParameters?: boolean; noImplicitUseStrict?: boolean; @@ -3369,7 +3369,8 @@ skipDefaultLibCheck?: boolean; sourceMap?: boolean; sourceRoot?: string; - strictNullChecks?: boolean; + strict?: boolean; + strictNullChecks?: boolean; // Always combine with strict property /* @internal */ stripInternal?: boolean; suppressExcessPropertyErrors?: boolean; suppressImplicitAnyIndexErrors?: boolean; From 65cea207dad1eb593fcc47454e29cc0735949687 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 3 Mar 2017 14:32:18 -0800 Subject: [PATCH 36/65] Use getTypeOfExpression when inferring variable type from initializer --- src/compiler/checker.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c189475fd4d..a4c0acc405d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16131,7 +16131,7 @@ namespace ts { } function checkDeclarationInitializer(declaration: VariableLikeDeclaration) { - const type = checkExpressionCached(declaration.initializer); + const type = getTypeOfExpression(declaration.initializer, /*cache*/ true); return getCombinedNodeFlags(declaration) & NodeFlags.Const || getCombinedModifierFlags(declaration) & ModifierFlags.Readonly && !isParameterPropertyDeclaration(declaration) || isTypeAssertion(declaration.initializer) ? type : getWidenedLiteralType(type); @@ -16204,10 +16204,12 @@ namespace ts { // Returns the type of an expression. Unlike checkExpression, this function is simply concerned // with computing the type and may not fully check all contained sub-expressions for errors. - function getTypeOfExpression(node: Expression) { + // A cache argument of true indicates that if the function performs a full type check, it is ok + // to cache the result. + function getTypeOfExpression(node: Expression, cache?: boolean) { // Optimize for the common case of a call to a function with a single non-generic call // signature where we can just fetch the return type without checking the arguments. - if (node.kind === SyntaxKind.CallExpression && (node).expression.kind !== SyntaxKind.SuperKeyword) { + if (node.kind === SyntaxKind.CallExpression && (node).expression.kind !== SyntaxKind.SuperKeyword && !isRequireCall(node, /*checkArgumentIsStringLiteral*/true)) { const funcType = checkNonNullExpression((node).expression); const signature = getSingleCallSignature(funcType); if (signature && !signature.typeParameters) { @@ -16217,7 +16219,7 @@ namespace ts { // Otherwise simply call checkExpression. Ideally, the entire family of checkXXX functions // should have a parameter that indicates whether full error checking is required such that // we can perform the optimizations locally. - return checkExpression(node); + return cache ? checkExpressionCached(node) : checkExpression(node); } // Checks an expression and returns its type. The contextualMapper parameter serves two purposes: When From 6995055c861c2983acc9901da8c9b07779e27b92 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 3 Mar 2017 14:32:59 -0800 Subject: [PATCH 37/65] Accept new baselines --- .../reference/ambientRequireFunction.types | 2 +- .../controlFlowIterationErrors.errors.txt | 18 +----------------- ...implicitAnyFromCircularInference.errors.txt | 5 +---- 3 files changed, 3 insertions(+), 22 deletions(-) diff --git a/tests/baselines/reference/ambientRequireFunction.types b/tests/baselines/reference/ambientRequireFunction.types index e0341d97ec3..7b01a59268f 100644 --- a/tests/baselines/reference/ambientRequireFunction.types +++ b/tests/baselines/reference/ambientRequireFunction.types @@ -3,7 +3,7 @@ const fs = require("fs"); >fs : typeof "fs" ->require("fs") : any +>require("fs") : typeof "fs" >require : (moduleName: string) => any >"fs" : "fs" diff --git a/tests/baselines/reference/controlFlowIterationErrors.errors.txt b/tests/baselines/reference/controlFlowIterationErrors.errors.txt index 1f090ccd35f..bc4b19b0602 100644 --- a/tests/baselines/reference/controlFlowIterationErrors.errors.txt +++ b/tests/baselines/reference/controlFlowIterationErrors.errors.txt @@ -6,15 +6,9 @@ tests/cases/conformance/controlFlow/controlFlowIterationErrors.ts(35,17): error Type 'string' is not assignable to type 'number'. tests/cases/conformance/controlFlow/controlFlowIterationErrors.ts(46,17): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'. Type 'string' is not assignable to type 'number'. -tests/cases/conformance/controlFlow/controlFlowIterationErrors.ts(77,13): error TS7022: 'y' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. -tests/cases/conformance/controlFlow/controlFlowIterationErrors.ts(77,26): error TS2345: Argument of type 'string | number | boolean' is not assignable to parameter of type 'string | number'. - Type 'true' is not assignable to type 'string | number'. -tests/cases/conformance/controlFlow/controlFlowIterationErrors.ts(88,13): error TS7022: 'y' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. -tests/cases/conformance/controlFlow/controlFlowIterationErrors.ts(88,26): error TS2345: Argument of type 'string | number | boolean' is not assignable to parameter of type 'string | number'. - Type 'true' is not assignable to type 'string | number'. -==== tests/cases/conformance/controlFlow/controlFlowIterationErrors.ts (8 errors) ==== +==== tests/cases/conformance/controlFlow/controlFlowIterationErrors.ts (4 errors) ==== let cond: boolean; @@ -104,11 +98,6 @@ tests/cases/conformance/controlFlow/controlFlowIterationErrors.ts(88,26): error x = "0"; while (cond) { let y = asNumber(x); - ~ -!!! error TS7022: 'y' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. - ~ -!!! error TS2345: Argument of type 'string | number | boolean' is not assignable to parameter of type 'string | number'. -!!! error TS2345: Type 'true' is not assignable to type 'string | number'. x = y + 1; x; } @@ -120,11 +109,6 @@ tests/cases/conformance/controlFlow/controlFlowIterationErrors.ts(88,26): error while (cond) { x; let y = asNumber(x); - ~ -!!! error TS7022: 'y' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. - ~ -!!! error TS2345: Argument of type 'string | number | boolean' is not assignable to parameter of type 'string | number'. -!!! error TS2345: Type 'true' is not assignable to type 'string | number'. x = y + 1; x; } diff --git a/tests/baselines/reference/implicitAnyFromCircularInference.errors.txt b/tests/baselines/reference/implicitAnyFromCircularInference.errors.txt index bb43d96b003..7d4dfa2cf5e 100644 --- a/tests/baselines/reference/implicitAnyFromCircularInference.errors.txt +++ b/tests/baselines/reference/implicitAnyFromCircularInference.errors.txt @@ -7,11 +7,10 @@ tests/cases/compiler/implicitAnyFromCircularInference.ts(18,10): error TS7024: F tests/cases/compiler/implicitAnyFromCircularInference.ts(23,10): error TS7024: Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions. tests/cases/compiler/implicitAnyFromCircularInference.ts(26,10): error TS7023: 'h' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions. tests/cases/compiler/implicitAnyFromCircularInference.ts(28,14): error TS7023: 'foo' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions. -tests/cases/compiler/implicitAnyFromCircularInference.ts(41,5): error TS7022: 's' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. tests/cases/compiler/implicitAnyFromCircularInference.ts(46,9): error TS7023: 'x' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions. -==== tests/cases/compiler/implicitAnyFromCircularInference.ts (11 errors) ==== +==== tests/cases/compiler/implicitAnyFromCircularInference.ts (10 errors) ==== // Error expected var a: typeof a; @@ -71,8 +70,6 @@ tests/cases/compiler/implicitAnyFromCircularInference.ts(46,9): error TS7023: 'x class C { // Error expected s = foo(this); - ~~~~~~~~~~~~~~ -!!! error TS7022: 's' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer. } class D { From c2431ade0cf271d2cbec7b651f06030493ec23a8 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 3 Mar 2017 14:33:07 -0800 Subject: [PATCH 38/65] Add regression test --- .../circularInferredTypeOfVariable.js | 44 +++++++++++++++++ .../circularInferredTypeOfVariable.symbols | 34 ++++++++++++++ .../circularInferredTypeOfVariable.types | 47 +++++++++++++++++++ .../circularInferredTypeOfVariable.ts | 20 ++++++++ 4 files changed, 145 insertions(+) create mode 100644 tests/baselines/reference/circularInferredTypeOfVariable.js create mode 100644 tests/baselines/reference/circularInferredTypeOfVariable.symbols create mode 100644 tests/baselines/reference/circularInferredTypeOfVariable.types create mode 100644 tests/cases/compiler/circularInferredTypeOfVariable.ts diff --git a/tests/baselines/reference/circularInferredTypeOfVariable.js b/tests/baselines/reference/circularInferredTypeOfVariable.js new file mode 100644 index 00000000000..38c5334761a --- /dev/null +++ b/tests/baselines/reference/circularInferredTypeOfVariable.js @@ -0,0 +1,44 @@ +//// [circularInferredTypeOfVariable.ts] + +// Repro from #14428 + +(async () => { + function foo(p: string[]): string[] { + return []; + } + + function bar(p: string[]): string[] { + return []; + } + + let a1: string[] | undefined = []; + + while (true) { + let a2 = foo(a1!); + a1 = await bar(a2); + } +}); + +//// [circularInferredTypeOfVariable.js] +// Repro from #14428 +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()); + }); +}; +(() => __awaiter(this, void 0, void 0, function* () { + function foo(p) { + return []; + } + function bar(p) { + return []; + } + let a1 = []; + while (true) { + let a2 = foo(a1); + a1 = yield bar(a2); + } +})); diff --git a/tests/baselines/reference/circularInferredTypeOfVariable.symbols b/tests/baselines/reference/circularInferredTypeOfVariable.symbols new file mode 100644 index 00000000000..653978f0e83 --- /dev/null +++ b/tests/baselines/reference/circularInferredTypeOfVariable.symbols @@ -0,0 +1,34 @@ +=== tests/cases/compiler/circularInferredTypeOfVariable.ts === + +// Repro from #14428 + +(async () => { + function foo(p: string[]): string[] { +>foo : Symbol(foo, Decl(circularInferredTypeOfVariable.ts, 3, 14)) +>p : Symbol(p, Decl(circularInferredTypeOfVariable.ts, 4, 17)) + + return []; + } + + function bar(p: string[]): string[] { +>bar : Symbol(bar, Decl(circularInferredTypeOfVariable.ts, 6, 5)) +>p : Symbol(p, Decl(circularInferredTypeOfVariable.ts, 8, 17)) + + return []; + } + + let a1: string[] | undefined = []; +>a1 : Symbol(a1, Decl(circularInferredTypeOfVariable.ts, 12, 7)) + + while (true) { + let a2 = foo(a1!); +>a2 : Symbol(a2, Decl(circularInferredTypeOfVariable.ts, 15, 11)) +>foo : Symbol(foo, Decl(circularInferredTypeOfVariable.ts, 3, 14)) +>a1 : Symbol(a1, Decl(circularInferredTypeOfVariable.ts, 12, 7)) + + a1 = await bar(a2); +>a1 : Symbol(a1, Decl(circularInferredTypeOfVariable.ts, 12, 7)) +>bar : Symbol(bar, Decl(circularInferredTypeOfVariable.ts, 6, 5)) +>a2 : Symbol(a2, Decl(circularInferredTypeOfVariable.ts, 15, 11)) + } +}); diff --git a/tests/baselines/reference/circularInferredTypeOfVariable.types b/tests/baselines/reference/circularInferredTypeOfVariable.types new file mode 100644 index 00000000000..df227bd9ae0 --- /dev/null +++ b/tests/baselines/reference/circularInferredTypeOfVariable.types @@ -0,0 +1,47 @@ +=== tests/cases/compiler/circularInferredTypeOfVariable.ts === + +// Repro from #14428 + +(async () => { +>(async () => { function foo(p: string[]): string[] { return []; } function bar(p: string[]): string[] { return []; } let a1: string[] | undefined = []; while (true) { let a2 = foo(a1!); a1 = await bar(a2); }}) : () => Promise +>async () => { function foo(p: string[]): string[] { return []; } function bar(p: string[]): string[] { return []; } let a1: string[] | undefined = []; while (true) { let a2 = foo(a1!); a1 = await bar(a2); }} : () => Promise + + function foo(p: string[]): string[] { +>foo : (p: string[]) => string[] +>p : string[] + + return []; +>[] : undefined[] + } + + function bar(p: string[]): string[] { +>bar : (p: string[]) => string[] +>p : string[] + + return []; +>[] : undefined[] + } + + let a1: string[] | undefined = []; +>a1 : string[] +>[] : undefined[] + + while (true) { +>true : true + + let a2 = foo(a1!); +>a2 : string[] +>foo(a1!) : string[] +>foo : (p: string[]) => string[] +>a1! : string[] +>a1 : string[] + + a1 = await bar(a2); +>a1 = await bar(a2) : string[] +>a1 : string[] +>await bar(a2) : string[] +>bar(a2) : string[] +>bar : (p: string[]) => string[] +>a2 : string[] + } +}); diff --git a/tests/cases/compiler/circularInferredTypeOfVariable.ts b/tests/cases/compiler/circularInferredTypeOfVariable.ts new file mode 100644 index 00000000000..662b6bfc8d8 --- /dev/null +++ b/tests/cases/compiler/circularInferredTypeOfVariable.ts @@ -0,0 +1,20 @@ +// @target: es6 + +// Repro from #14428 + +(async () => { + function foo(p: string[]): string[] { + return []; + } + + function bar(p: string[]): string[] { + return []; + } + + let a1: string[] | undefined = []; + + while (true) { + let a2 = foo(a1!); + a1 = await bar(a2); + } +}); \ No newline at end of file From 56e2735f5677811d5b519e18b0a48d352c79f647 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 3 Mar 2017 14:57:14 -0800 Subject: [PATCH 39/65] Fix fourslash test --- tests/cases/fourslash/extendArrayInterfaceMember.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cases/fourslash/extendArrayInterfaceMember.ts b/tests/cases/fourslash/extendArrayInterfaceMember.ts index ef3c06b2053..22aeed01f1d 100644 --- a/tests/cases/fourslash/extendArrayInterfaceMember.ts +++ b/tests/cases/fourslash/extendArrayInterfaceMember.ts @@ -10,7 +10,7 @@ verify.numberOfErrorsInCurrentFile(1); // - Supplied parameters do not match any signature of call target. // - Could not select overload for 'call' expression. -verify.quickInfoAt("y", "var y: any"); +verify.quickInfoAt("y", "var y: number"); goTo.eof(); edit.insert("interface Array { pop(def: T): T; }"); From efea81b8a038089c28a03dd03225e1a2b309a9f1 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 5 Mar 2017 14:07:33 -0800 Subject: [PATCH 40/65] Add failing repro --- .../controlFlow/typeGuardsTypeParameters.ts | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 tests/cases/conformance/controlFlow/typeGuardsTypeParameters.ts diff --git a/tests/cases/conformance/controlFlow/typeGuardsTypeParameters.ts b/tests/cases/conformance/controlFlow/typeGuardsTypeParameters.ts new file mode 100644 index 00000000000..169dbc7a7c8 --- /dev/null +++ b/tests/cases/conformance/controlFlow/typeGuardsTypeParameters.ts @@ -0,0 +1,35 @@ +// @strictNullChecks: true + +// Type guards involving type parameters produce intersection types + +class C { + prop: string; +} + +function f1(x: T) { + if (x instanceof C) { + let v1: T = x; + let v2: C = x; + x.prop; + } +} + +function f2(x: T) { + if (typeof x === "string") { + let v1: T = x; + let v2: string = x; + x.length; + } +} + +// Repro from #13872 + +function fun(item: { [P in keyof T]: T[P] }) { + const strings: string[] = []; + for (const key in item) { + const value = item[key]; + if (typeof value === "string") { + strings.push(value); + } + } +} From 4c71a7c084744cb7d29011c3757822242c64db18 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 5 Mar 2017 14:12:13 -0800 Subject: [PATCH 41/65] Accept error baselines --- .../typeGuardsTypeParameters.errors.txt | 47 +++++++++++++ .../reference/typeGuardsTypeParameters.js | 68 +++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 tests/baselines/reference/typeGuardsTypeParameters.errors.txt create mode 100644 tests/baselines/reference/typeGuardsTypeParameters.js diff --git a/tests/baselines/reference/typeGuardsTypeParameters.errors.txt b/tests/baselines/reference/typeGuardsTypeParameters.errors.txt new file mode 100644 index 00000000000..46eb198f425 --- /dev/null +++ b/tests/baselines/reference/typeGuardsTypeParameters.errors.txt @@ -0,0 +1,47 @@ +tests/cases/conformance/controlFlow/typeGuardsTypeParameters.ts(10,13): error TS2322: Type 'C' is not assignable to type 'T'. +tests/cases/conformance/controlFlow/typeGuardsTypeParameters.ts(20,11): error TS2339: Property 'length' does not exist on type 'never'. +tests/cases/conformance/controlFlow/typeGuardsTypeParameters.ts(31,26): error TS2345: Argument of type 'T[keyof T]' is not assignable to parameter of type 'string'. + + +==== tests/cases/conformance/controlFlow/typeGuardsTypeParameters.ts (3 errors) ==== + + // Type guards involving type parameters produce intersection types + + class C { + prop: string; + } + + function f1(x: T) { + if (x instanceof C) { + let v1: T = x; + ~~ +!!! error TS2322: Type 'C' is not assignable to type 'T'. + let v2: C = x; + x.prop; + } + } + + function f2(x: T) { + if (typeof x === "string") { + let v1: T = x; + let v2: string = x; + x.length; + ~~~~~~ +!!! error TS2339: Property 'length' does not exist on type 'never'. + } + } + + // Repro from #13872 + + function fun(item: { [P in keyof T]: T[P] }) { + const strings: string[] = []; + for (const key in item) { + const value = item[key]; + if (typeof value === "string") { + strings.push(value); + ~~~~~ +!!! error TS2345: Argument of type 'T[keyof T]' is not assignable to parameter of type 'string'. + } + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/typeGuardsTypeParameters.js b/tests/baselines/reference/typeGuardsTypeParameters.js new file mode 100644 index 00000000000..bf0b1d2bac2 --- /dev/null +++ b/tests/baselines/reference/typeGuardsTypeParameters.js @@ -0,0 +1,68 @@ +//// [typeGuardsTypeParameters.ts] + +// Type guards involving type parameters produce intersection types + +class C { + prop: string; +} + +function f1(x: T) { + if (x instanceof C) { + let v1: T = x; + let v2: C = x; + x.prop; + } +} + +function f2(x: T) { + if (typeof x === "string") { + let v1: T = x; + let v2: string = x; + x.length; + } +} + +// Repro from #13872 + +function fun(item: { [P in keyof T]: T[P] }) { + const strings: string[] = []; + for (const key in item) { + const value = item[key]; + if (typeof value === "string") { + strings.push(value); + } + } +} + + +//// [typeGuardsTypeParameters.js] +// Type guards involving type parameters produce intersection types +var C = (function () { + function C() { + } + return C; +}()); +function f1(x) { + if (x instanceof C) { + var v1 = x; + var v2 = x; + x.prop; + } +} +function f2(x) { + if (typeof x === "string") { + var v1 = x; + var v2 = x; + x.length; + } +} +// Repro from #13872 +function fun(item) { + var strings = []; + for (var key in item) { + var value = item[key]; + if (typeof value === "string") { + strings.push(value); + } + } +} From 91b658da36e1b9a4eb6f19aec6d88f69cbc193c6 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 5 Mar 2017 14:12:55 -0800 Subject: [PATCH 42/65] Construct intersection types for type guards involving type parameters --- src/compiler/checker.ts | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a4c0acc405d..5685e54542f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9843,9 +9843,8 @@ namespace ts { if (flags & TypeFlags.NonPrimitive) { return strictNullChecks ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts; } - if (flags & TypeFlags.TypeParameter) { - const constraint = getConstraintOfTypeParameter(type); - return getTypeFacts(constraint || emptyObjectType); + if (flags & TypeFlags.TypeVariable) { + return getTypeFacts(getBaseConstraintOfType(type) || emptyObjectType); } if (flags & TypeFlags.UnionOrIntersection) { return getTypeFactsOfTypes((type).types); @@ -10632,8 +10631,16 @@ namespace ts { // is a supertype of that primitive type. For example, type 'any' can be narrowed // to one of the primitive types. const targetType = typeofTypesByName.get(literal.text); - if (targetType && isTypeSubtypeOf(targetType, type)) { - return targetType; + if (targetType) { + if (isTypeSubtypeOf(targetType, type)) { + return targetType; + } + if (type.flags & TypeFlags.TypeVariable) { + const constraint = getBaseConstraintOfType(type) || anyType; + if (isTypeSubtypeOf(targetType, constraint)) { + return getIntersectionType([type, targetType]); + } + } } } const facts = assumeTrue ? @@ -10731,10 +10738,9 @@ namespace ts { // Otherwise, if the candidate type is assignable to the target type, narrow to the candidate // type. Otherwise, the types are completely unrelated, so narrow to an intersection of the // two types. - const targetType = type.flags & TypeFlags.TypeParameter ? getApparentType(type) : type; return isTypeSubtypeOf(candidate, type) ? candidate : isTypeAssignableTo(type, candidate) ? type : - isTypeAssignableTo(candidate, targetType) ? candidate : + isTypeAssignableTo(candidate, type) ? candidate : getIntersectionType([type, candidate]); } From af686adf1f64fb31bd6f212777e6ee4f8ff2402e Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 5 Mar 2017 14:19:20 -0800 Subject: [PATCH 43/65] Accept new baselines --- .../typeGuardsTypeParameters.errors.txt | 47 -------- .../typeGuardsTypeParameters.symbols | 98 ++++++++++++++++ .../reference/typeGuardsTypeParameters.types | 108 ++++++++++++++++++ 3 files changed, 206 insertions(+), 47 deletions(-) delete mode 100644 tests/baselines/reference/typeGuardsTypeParameters.errors.txt create mode 100644 tests/baselines/reference/typeGuardsTypeParameters.symbols create mode 100644 tests/baselines/reference/typeGuardsTypeParameters.types diff --git a/tests/baselines/reference/typeGuardsTypeParameters.errors.txt b/tests/baselines/reference/typeGuardsTypeParameters.errors.txt deleted file mode 100644 index 46eb198f425..00000000000 --- a/tests/baselines/reference/typeGuardsTypeParameters.errors.txt +++ /dev/null @@ -1,47 +0,0 @@ -tests/cases/conformance/controlFlow/typeGuardsTypeParameters.ts(10,13): error TS2322: Type 'C' is not assignable to type 'T'. -tests/cases/conformance/controlFlow/typeGuardsTypeParameters.ts(20,11): error TS2339: Property 'length' does not exist on type 'never'. -tests/cases/conformance/controlFlow/typeGuardsTypeParameters.ts(31,26): error TS2345: Argument of type 'T[keyof T]' is not assignable to parameter of type 'string'. - - -==== tests/cases/conformance/controlFlow/typeGuardsTypeParameters.ts (3 errors) ==== - - // Type guards involving type parameters produce intersection types - - class C { - prop: string; - } - - function f1(x: T) { - if (x instanceof C) { - let v1: T = x; - ~~ -!!! error TS2322: Type 'C' is not assignable to type 'T'. - let v2: C = x; - x.prop; - } - } - - function f2(x: T) { - if (typeof x === "string") { - let v1: T = x; - let v2: string = x; - x.length; - ~~~~~~ -!!! error TS2339: Property 'length' does not exist on type 'never'. - } - } - - // Repro from #13872 - - function fun(item: { [P in keyof T]: T[P] }) { - const strings: string[] = []; - for (const key in item) { - const value = item[key]; - if (typeof value === "string") { - strings.push(value); - ~~~~~ -!!! error TS2345: Argument of type 'T[keyof T]' is not assignable to parameter of type 'string'. - } - } - } - \ No newline at end of file diff --git a/tests/baselines/reference/typeGuardsTypeParameters.symbols b/tests/baselines/reference/typeGuardsTypeParameters.symbols new file mode 100644 index 00000000000..53e6086c0fd --- /dev/null +++ b/tests/baselines/reference/typeGuardsTypeParameters.symbols @@ -0,0 +1,98 @@ +=== tests/cases/conformance/controlFlow/typeGuardsTypeParameters.ts === + +// Type guards involving type parameters produce intersection types + +class C { +>C : Symbol(C, Decl(typeGuardsTypeParameters.ts, 0, 0)) + + prop: string; +>prop : Symbol(C.prop, Decl(typeGuardsTypeParameters.ts, 3, 9)) +} + +function f1(x: T) { +>f1 : Symbol(f1, Decl(typeGuardsTypeParameters.ts, 5, 1)) +>T : Symbol(T, Decl(typeGuardsTypeParameters.ts, 7, 12)) +>x : Symbol(x, Decl(typeGuardsTypeParameters.ts, 7, 15)) +>T : Symbol(T, Decl(typeGuardsTypeParameters.ts, 7, 12)) + + if (x instanceof C) { +>x : Symbol(x, Decl(typeGuardsTypeParameters.ts, 7, 15)) +>C : Symbol(C, Decl(typeGuardsTypeParameters.ts, 0, 0)) + + let v1: T = x; +>v1 : Symbol(v1, Decl(typeGuardsTypeParameters.ts, 9, 11)) +>T : Symbol(T, Decl(typeGuardsTypeParameters.ts, 7, 12)) +>x : Symbol(x, Decl(typeGuardsTypeParameters.ts, 7, 15)) + + let v2: C = x; +>v2 : Symbol(v2, Decl(typeGuardsTypeParameters.ts, 10, 11)) +>C : Symbol(C, Decl(typeGuardsTypeParameters.ts, 0, 0)) +>x : Symbol(x, Decl(typeGuardsTypeParameters.ts, 7, 15)) + + x.prop; +>x.prop : Symbol(C.prop, Decl(typeGuardsTypeParameters.ts, 3, 9)) +>x : Symbol(x, Decl(typeGuardsTypeParameters.ts, 7, 15)) +>prop : Symbol(C.prop, Decl(typeGuardsTypeParameters.ts, 3, 9)) + } +} + +function f2(x: T) { +>f2 : Symbol(f2, Decl(typeGuardsTypeParameters.ts, 13, 1)) +>T : Symbol(T, Decl(typeGuardsTypeParameters.ts, 15, 12)) +>x : Symbol(x, Decl(typeGuardsTypeParameters.ts, 15, 15)) +>T : Symbol(T, Decl(typeGuardsTypeParameters.ts, 15, 12)) + + if (typeof x === "string") { +>x : Symbol(x, Decl(typeGuardsTypeParameters.ts, 15, 15)) + + let v1: T = x; +>v1 : Symbol(v1, Decl(typeGuardsTypeParameters.ts, 17, 11)) +>T : Symbol(T, Decl(typeGuardsTypeParameters.ts, 15, 12)) +>x : Symbol(x, Decl(typeGuardsTypeParameters.ts, 15, 15)) + + let v2: string = x; +>v2 : Symbol(v2, Decl(typeGuardsTypeParameters.ts, 18, 11)) +>x : Symbol(x, Decl(typeGuardsTypeParameters.ts, 15, 15)) + + x.length; +>x.length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(typeGuardsTypeParameters.ts, 15, 15)) +>length : Symbol(String.length, Decl(lib.d.ts, --, --)) + } +} + +// Repro from #13872 + +function fun(item: { [P in keyof T]: T[P] }) { +>fun : Symbol(fun, Decl(typeGuardsTypeParameters.ts, 21, 1)) +>T : Symbol(T, Decl(typeGuardsTypeParameters.ts, 25, 13)) +>item : Symbol(item, Decl(typeGuardsTypeParameters.ts, 25, 16)) +>P : Symbol(P, Decl(typeGuardsTypeParameters.ts, 25, 25)) +>T : Symbol(T, Decl(typeGuardsTypeParameters.ts, 25, 13)) +>T : Symbol(T, Decl(typeGuardsTypeParameters.ts, 25, 13)) +>P : Symbol(P, Decl(typeGuardsTypeParameters.ts, 25, 25)) + + const strings: string[] = []; +>strings : Symbol(strings, Decl(typeGuardsTypeParameters.ts, 26, 9)) + + for (const key in item) { +>key : Symbol(key, Decl(typeGuardsTypeParameters.ts, 27, 14)) +>item : Symbol(item, Decl(typeGuardsTypeParameters.ts, 25, 16)) + + const value = item[key]; +>value : Symbol(value, Decl(typeGuardsTypeParameters.ts, 28, 13)) +>item : Symbol(item, Decl(typeGuardsTypeParameters.ts, 25, 16)) +>key : Symbol(key, Decl(typeGuardsTypeParameters.ts, 27, 14)) + + if (typeof value === "string") { +>value : Symbol(value, Decl(typeGuardsTypeParameters.ts, 28, 13)) + + strings.push(value); +>strings.push : Symbol(Array.push, Decl(lib.d.ts, --, --)) +>strings : Symbol(strings, Decl(typeGuardsTypeParameters.ts, 26, 9)) +>push : Symbol(Array.push, Decl(lib.d.ts, --, --)) +>value : Symbol(value, Decl(typeGuardsTypeParameters.ts, 28, 13)) + } + } +} + diff --git a/tests/baselines/reference/typeGuardsTypeParameters.types b/tests/baselines/reference/typeGuardsTypeParameters.types new file mode 100644 index 00000000000..6825402cdc7 --- /dev/null +++ b/tests/baselines/reference/typeGuardsTypeParameters.types @@ -0,0 +1,108 @@ +=== tests/cases/conformance/controlFlow/typeGuardsTypeParameters.ts === + +// Type guards involving type parameters produce intersection types + +class C { +>C : C + + prop: string; +>prop : string +} + +function f1(x: T) { +>f1 : (x: T) => void +>T : T +>x : T +>T : T + + if (x instanceof C) { +>x instanceof C : boolean +>x : T +>C : typeof C + + let v1: T = x; +>v1 : T +>T : T +>x : T & C + + let v2: C = x; +>v2 : C +>C : C +>x : T & C + + x.prop; +>x.prop : string +>x : T & C +>prop : string + } +} + +function f2(x: T) { +>f2 : (x: T) => void +>T : T +>x : T +>T : T + + if (typeof x === "string") { +>typeof x === "string" : boolean +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" +>x : T +>"string" : "string" + + let v1: T = x; +>v1 : T +>T : T +>x : T & string + + let v2: string = x; +>v2 : string +>x : T & string + + x.length; +>x.length : number +>x : T & string +>length : number + } +} + +// Repro from #13872 + +function fun(item: { [P in keyof T]: T[P] }) { +>fun : (item: { [P in keyof T]: T[P]; }) => void +>T : T +>item : { [P in keyof T]: T[P]; } +>P : P +>T : T +>T : T +>P : P + + const strings: string[] = []; +>strings : string[] +>[] : never[] + + for (const key in item) { +>key : keyof T +>item : { [P in keyof T]: T[P]; } + + const value = item[key]; +>value : T[keyof T] +>item[key] : T[keyof T] +>item : { [P in keyof T]: T[P]; } +>key : keyof T + + if (typeof value === "string") { +>typeof value === "string" : boolean +>typeof value : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" +>value : T[keyof T] +>"string" : "string" + + strings.push(value); +>strings.push(value) : number +>strings.push : (...items: string[]) => number +>strings : string[] +>push : (...items: string[]) => number +>value : T[keyof T] & string + } + } +} + From b1520345bec020280c3cd8a38fca5f0d43f4761e Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Sun, 5 Mar 2017 15:41:47 -0800 Subject: [PATCH 44/65] use ES6 library when building tslint rules (#14474) --- Jakefile.js | 12 +++++++++--- scripts/parallel-lint.js | 3 ++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Jakefile.js b/Jakefile.js index f8be7c2b671..4512aa23794 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -328,8 +328,14 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts if (opts.stripInternal) { options += " --stripInternal"; } - - options += " --target es5 --lib es5,scripthost --noUnusedLocals --noUnusedParameters"; + options += " --target es5"; + if (opts.lib) { + options += " --lib " + opts.lib + } + else { + options += " --lib es5,scripthost" + } + options += " --noUnusedLocals --noUnusedParameters"; var cmd = host + " " + compilerPath + " " + options + " "; cmd = cmd + sources.join(" "); @@ -1110,7 +1116,7 @@ desc("Compiles tslint rules to js"); task("build-rules", ["build-rules-start"].concat(tslintRulesOutFiles).concat(["build-rules-end"])); tslintRulesFiles.forEach(function (ruleFile, i) { compileFile(tslintRulesOutFiles[i], [ruleFile], [ruleFile], [], /*useBuiltCompiler*/ false, - { noOutFile: true, generateDeclarations: false, outDir: path.join(builtLocalDirectory, "tslint") }); + { noOutFile: true, generateDeclarations: false, outDir: path.join(builtLocalDirectory, "tslint"), lib: "es6" }); }); desc("Emit the start of the build-rules fold"); diff --git a/scripts/parallel-lint.js b/scripts/parallel-lint.js index aec9960ce47..2ac84667d6f 100644 --- a/scripts/parallel-lint.js +++ b/scripts/parallel-lint.js @@ -1,5 +1,6 @@ var tslint = require("tslint"); var fs = require("fs"); +var path = require("path"); function getLinterOptions() { return { @@ -9,7 +10,7 @@ function getLinterOptions() { }; } function getLinterConfiguration() { - return require("../tslint.json"); + return tslint.Configuration.loadConfigurationFromPath(path.join(__dirname, "../tslint.json")); } function lintFileContents(options, configuration, path, contents) { From 7ed13d0c1ef96b2408cdaf39d57ba5c889fc9708 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 5 Mar 2017 16:51:58 -0800 Subject: [PATCH 45/65] Accept new tsconfig baselines --- .../tsConfig/Default initialized TSConfig/tsconfig.json | 2 +- .../tsconfig.json | 2 +- .../tsconfig.json | 2 +- .../Initialized TSConfig with files options/tsconfig.json | 2 +- .../tsconfig.json | 2 +- .../tsconfig.json | 2 +- .../tsconfig.json | 2 +- .../tsconfig.json | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json b/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json index ea891967cb5..74db1904dda 100644 --- a/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "module": "commonjs", "target": "es5", - "noImplicitAny": false, + "strict": false, "sourceMap": false } } \ No newline at end of file diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json index abe135b4f16..8277fa5f4a2 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "module": "commonjs", "target": "es5", - "noImplicitAny": false, + "strict": false, "sourceMap": false, "noUnusedLocals": true } diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json index e28b66c8c2b..2402c4145a0 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "module": "commonjs", "target": "es5", - "noImplicitAny": false, + "strict": false, "sourceMap": false, "jsx": "react" } diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json index 5273b3cb7c8..d73d25d9b9b 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "module": "commonjs", "target": "es5", - "noImplicitAny": false, + "strict": false, "sourceMap": false }, "files": [ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json index fa9cb6cad84..7f7bde79e92 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "module": "commonjs", "target": "es5", - "noImplicitAny": false, + "strict": false, "sourceMap": false, "lib": [ "es5", diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json index ea891967cb5..74db1904dda 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "module": "commonjs", "target": "es5", - "noImplicitAny": false, + "strict": false, "sourceMap": false } } \ No newline at end of file diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json index 3ff8208d9d6..587f661f1f0 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "module": "commonjs", "target": "es5", - "noImplicitAny": false, + "strict": false, "sourceMap": false, "lib": [ "es5", diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json index b1740ac4c12..4d6974281ce 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "module": "commonjs", "target": "es5", - "noImplicitAny": false, + "strict": false, "sourceMap": false, "types": [ "jquery", From cc77225f35d8a04ea0288ec37c1c825eb4be6903 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Mon, 6 Mar 2017 06:21:56 -0800 Subject: [PATCH 46/65] Go back to using tslint@next --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8b52eb6675e..3ffab4bfb13 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "through2": "latest", "travis-fold": "latest", "ts-node": "latest", - "tslint": "latest", + "tslint": "next", "typescript": "next" }, "scripts": { From d3b7058c2999f68c04278e15cbc29c91bcc44dc5 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 6 Mar 2017 13:04:59 -0800 Subject: [PATCH 47/65] Change 'tsc --init' to default to 'strict: true' --- src/compiler/commandLineParser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 17bbbcb8a56..dc692972891 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -525,7 +525,7 @@ namespace ts { export const defaultInitCompilerOptions: CompilerOptions = { module: ModuleKind.CommonJS, target: ScriptTarget.ES5, - strict: false, + strict: true, sourceMap: false, }; From de120b32e912e57886df689e291798dfa66c04db Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 6 Mar 2017 13:05:14 -0800 Subject: [PATCH 48/65] Accept new baselines --- .../tsConfig/Default initialized TSConfig/tsconfig.json | 2 +- .../tsconfig.json | 2 +- .../tsconfig.json | 2 +- .../Initialized TSConfig with files options/tsconfig.json | 2 +- .../tsconfig.json | 2 +- .../tsconfig.json | 2 +- .../tsconfig.json | 2 +- .../tsconfig.json | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json b/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json index 74db1904dda..a4c1c449095 100644 --- a/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "module": "commonjs", "target": "es5", - "strict": false, + "strict": true, "sourceMap": false } } \ No newline at end of file diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json index 8277fa5f4a2..23061360bc2 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "module": "commonjs", "target": "es5", - "strict": false, + "strict": true, "sourceMap": false, "noUnusedLocals": true } diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json index 2402c4145a0..16535c7960a 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "module": "commonjs", "target": "es5", - "strict": false, + "strict": true, "sourceMap": false, "jsx": "react" } diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json index d73d25d9b9b..133de87dc1d 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "module": "commonjs", "target": "es5", - "strict": false, + "strict": true, "sourceMap": false }, "files": [ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json index 7f7bde79e92..2ab8d9412ea 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "module": "commonjs", "target": "es5", - "strict": false, + "strict": true, "sourceMap": false, "lib": [ "es5", diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json index 74db1904dda..a4c1c449095 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "module": "commonjs", "target": "es5", - "strict": false, + "strict": true, "sourceMap": false } } \ No newline at end of file diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json index 587f661f1f0..5716902e02c 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "module": "commonjs", "target": "es5", - "strict": false, + "strict": true, "sourceMap": false, "lib": [ "es5", diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json index 4d6974281ce..4fc209f9b9c 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "module": "commonjs", "target": "es5", - "strict": false, + "strict": true, "sourceMap": false, "types": [ "jquery", From ed071a9b02eedab11909c8a7e4736a53f0011361 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Mon, 6 Mar 2017 13:33:51 -0800 Subject: [PATCH 49/65] Only emit ESModule marker when there is no export equal and the file is external module --- src/compiler/transformers/module/module.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index 52c6db707c1..c1f18e2021b 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -55,9 +55,7 @@ namespace ts { * @param node The SourceFile node. */ function transformSourceFile(node: SourceFile) { - if (isDeclarationFile(node) - || !(isExternalModule(node) - || compilerOptions.isolatedModules)) { + if (isDeclarationFile(node) || !(isExternalModule(node) || compilerOptions.isolatedModules)) { return node; } @@ -74,6 +72,14 @@ namespace ts { return aggregateTransformFlags(updated); } + + function shouldEmitUnderscoreUnderscoreESModule() { + if (!currentModuleInfo.exportEquals && isExternalModule(currentSourceFile)) { + return true; + } + return false; + } + /** * Transforms a SourceFile into a CommonJS module. * @@ -85,7 +91,7 @@ namespace ts { const statements: Statement[] = []; const statementOffset = addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, sourceElementVisitor); - if (!currentModuleInfo.exportEquals) { + if (shouldEmitUnderscoreUnderscoreESModule()) { append(statements, createUnderscoreUnderscoreESModule()); } @@ -378,7 +384,7 @@ namespace ts { const statements: Statement[] = []; const statementOffset = addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, sourceElementVisitor); - if (!currentModuleInfo.exportEquals) { + if (shouldEmitUnderscoreUnderscoreESModule()) { append(statements, createUnderscoreUnderscoreESModule()); } From 6a2d2608c355cab6a6b0143be93cfc86f4fdfe58 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Mon, 6 Mar 2017 13:36:54 -0800 Subject: [PATCH 50/65] Update baselines --- tests/baselines/reference/importHelpersInIsolatedModules.js | 1 - tests/baselines/reference/isolatedModulesPlainFile-AMD.js | 1 - tests/baselines/reference/isolatedModulesPlainFile-CommonJS.js | 1 - tests/baselines/reference/isolatedModulesPlainFile-UMD.js | 1 - .../transpile/Does not generate semantic diagnostics.js | 1 - .../transpile/Generates expected syntactic diagnostics.js | 1 - tests/baselines/reference/transpile/Generates module output.js | 1 - .../Generates no diagnostics for missing file references.js | 1 - .../transpile/Generates no diagnostics with valid inputs.js | 1 - .../transpile/No extra errors for file without extension.js | 1 - ...an error when compiler-options module-kind is out-of-range.js | 1 - ... error when compiler-options target-script is out-of-range.js | 1 - .../reference/transpile/Support options with lib values.js | 1 - .../reference/transpile/Support options with types values.js | 1 - .../reference/transpile/Supports backslashes in file name.js | 1 - tests/baselines/reference/transpile/Supports setting allowJs.js | 1 - .../transpile/Supports setting allowSyntheticDefaultImports.js | 1 - .../reference/transpile/Supports setting allowUnreachableCode.js | 1 - .../reference/transpile/Supports setting allowUnusedLabels.js | 1 - .../reference/transpile/Supports setting alwaysStrict.js | 1 - tests/baselines/reference/transpile/Supports setting baseUrl.js | 1 - tests/baselines/reference/transpile/Supports setting charset.js | 1 - .../reference/transpile/Supports setting declaration.js | 1 - .../reference/transpile/Supports setting declarationDir.js | 1 - tests/baselines/reference/transpile/Supports setting emitBOM.js | 1 - .../transpile/Supports setting emitDecoratorMetadata.js | 1 - .../transpile/Supports setting experimentalDecorators.js | 1 - .../Supports setting forceConsistentCasingInFileNames.js | 1 - .../reference/transpile/Supports setting isolatedModules.js | 1 - tests/baselines/reference/transpile/Supports setting jsx.js | 1 - .../baselines/reference/transpile/Supports setting jsxFactory.js | 1 - tests/baselines/reference/transpile/Supports setting lib.js | 1 - tests/baselines/reference/transpile/Supports setting locale.js | 1 - tests/baselines/reference/transpile/Supports setting module.js | 1 - .../reference/transpile/Supports setting moduleResolution.js | 1 - tests/baselines/reference/transpile/Supports setting newLine.js | 1 - tests/baselines/reference/transpile/Supports setting noEmit.js | 1 - .../reference/transpile/Supports setting noEmitHelpers.js | 1 - .../reference/transpile/Supports setting noEmitOnError.js | 1 - .../reference/transpile/Supports setting noErrorTruncation.js | 1 - .../transpile/Supports setting noFallthroughCasesInSwitch.js | 1 - .../reference/transpile/Supports setting noImplicitAny.js | 1 - .../reference/transpile/Supports setting noImplicitReturns.js | 1 - .../reference/transpile/Supports setting noImplicitThis.js | 1 - .../reference/transpile/Supports setting noImplicitUseStrict.js | 1 - tests/baselines/reference/transpile/Supports setting noLib.js | 1 - .../baselines/reference/transpile/Supports setting noResolve.js | 1 - tests/baselines/reference/transpile/Supports setting out.js | 1 - tests/baselines/reference/transpile/Supports setting outDir.js | 1 - tests/baselines/reference/transpile/Supports setting outFile.js | 1 - tests/baselines/reference/transpile/Supports setting paths.js | 1 - .../reference/transpile/Supports setting preserveConstEnums.js | 1 - .../reference/transpile/Supports setting reactNamespace.js | 1 - .../reference/transpile/Supports setting removeComments.js | 1 - tests/baselines/reference/transpile/Supports setting rootDir.js | 1 - tests/baselines/reference/transpile/Supports setting rootDirs.js | 1 - .../reference/transpile/Supports setting skipDefaultLibCheck.js | 1 - .../reference/transpile/Supports setting skipLibCheck.js | 1 - .../reference/transpile/Supports setting strictNullChecks.js | 1 - .../reference/transpile/Supports setting stripInternal.js | 1 - .../transpile/Supports setting suppressExcessPropertyErrors.js | 1 - .../transpile/Supports setting suppressImplicitAnyIndexErrors.js | 1 - .../baselines/reference/transpile/Supports setting typeRoots.js | 1 - tests/baselines/reference/transpile/Supports setting types.js | 1 - .../baselines/reference/transpile/Supports urls in file name.js | 1 - .../reference/transpile/Uses correct newLine character.js | 1 - tests/baselines/reference/transpile/transpile .js files.js | 1 - .../transpile/transpile file as tsx if jsx is specified.js | 1 - 68 files changed, 68 deletions(-) diff --git a/tests/baselines/reference/importHelpersInIsolatedModules.js b/tests/baselines/reference/importHelpersInIsolatedModules.js index 72a91ac365e..454fde430d3 100644 --- a/tests/baselines/reference/importHelpersInIsolatedModules.js +++ b/tests/baselines/reference/importHelpersInIsolatedModules.js @@ -69,7 +69,6 @@ C = tslib_1.__decorate([ ], C); //// [script.js] "use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); var tslib_1 = require("tslib"); var A = (function () { function A() { diff --git a/tests/baselines/reference/isolatedModulesPlainFile-AMD.js b/tests/baselines/reference/isolatedModulesPlainFile-AMD.js index 4ed1fdf2c77..1e45ee159d6 100644 --- a/tests/baselines/reference/isolatedModulesPlainFile-AMD.js +++ b/tests/baselines/reference/isolatedModulesPlainFile-AMD.js @@ -7,6 +7,5 @@ run(1); //// [isolatedModulesPlainFile-AMD.js] define(["require", "exports"], function (require, exports) { "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); run(1); }); diff --git a/tests/baselines/reference/isolatedModulesPlainFile-CommonJS.js b/tests/baselines/reference/isolatedModulesPlainFile-CommonJS.js index 38739a700ef..f40d2173685 100644 --- a/tests/baselines/reference/isolatedModulesPlainFile-CommonJS.js +++ b/tests/baselines/reference/isolatedModulesPlainFile-CommonJS.js @@ -6,5 +6,4 @@ run(1); //// [isolatedModulesPlainFile-CommonJS.js] "use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); run(1); diff --git a/tests/baselines/reference/isolatedModulesPlainFile-UMD.js b/tests/baselines/reference/isolatedModulesPlainFile-UMD.js index f37962a84ab..ece949b9100 100644 --- a/tests/baselines/reference/isolatedModulesPlainFile-UMD.js +++ b/tests/baselines/reference/isolatedModulesPlainFile-UMD.js @@ -15,6 +15,5 @@ run(1); } })(function (require, exports) { "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); run(1); }); diff --git a/tests/baselines/reference/transpile/Does not generate semantic diagnostics.js b/tests/baselines/reference/transpile/Does not generate semantic diagnostics.js index 4571caffa31..61a703e13bb 100644 --- a/tests/baselines/reference/transpile/Does not generate semantic diagnostics.js +++ b/tests/baselines/reference/transpile/Does not generate semantic diagnostics.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; var x = 0; //# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Generates expected syntactic diagnostics.js b/tests/baselines/reference/transpile/Generates expected syntactic diagnostics.js index 4d133b7655c..9d108d63313 100644 --- a/tests/baselines/reference/transpile/Generates expected syntactic diagnostics.js +++ b/tests/baselines/reference/transpile/Generates expected syntactic diagnostics.js @@ -1,5 +1,4 @@ "use strict"; -exports.__esModule = true; a; b; //# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Generates module output.js b/tests/baselines/reference/transpile/Generates module output.js index 2c7bb7add09..9eadd1f2717 100644 --- a/tests/baselines/reference/transpile/Generates module output.js +++ b/tests/baselines/reference/transpile/Generates module output.js @@ -1,6 +1,5 @@ define(["require", "exports"], function (require, exports) { "use strict"; - exports.__esModule = true; var x = 0; }); //# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Generates no diagnostics for missing file references.js b/tests/baselines/reference/transpile/Generates no diagnostics for missing file references.js index 04ba1d12e5e..88d98628eee 100644 --- a/tests/baselines/reference/transpile/Generates no diagnostics for missing file references.js +++ b/tests/baselines/reference/transpile/Generates no diagnostics for missing file references.js @@ -1,5 +1,4 @@ "use strict"; -exports.__esModule = true; /// var x = 0; //# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Generates no diagnostics with valid inputs.js b/tests/baselines/reference/transpile/Generates no diagnostics with valid inputs.js index 4571caffa31..61a703e13bb 100644 --- a/tests/baselines/reference/transpile/Generates no diagnostics with valid inputs.js +++ b/tests/baselines/reference/transpile/Generates no diagnostics with valid inputs.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; var x = 0; //# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/No extra errors for file without extension.js b/tests/baselines/reference/transpile/No extra errors for file without extension.js index 4571caffa31..61a703e13bb 100644 --- a/tests/baselines/reference/transpile/No extra errors for file without extension.js +++ b/tests/baselines/reference/transpile/No extra errors for file without extension.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; var x = 0; //# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Report an error when compiler-options module-kind is out-of-range.js b/tests/baselines/reference/transpile/Report an error when compiler-options module-kind is out-of-range.js index e9493d9d591..1ceb1bcd146 100644 --- a/tests/baselines/reference/transpile/Report an error when compiler-options module-kind is out-of-range.js +++ b/tests/baselines/reference/transpile/Report an error when compiler-options module-kind is out-of-range.js @@ -1,3 +1,2 @@ "use strict"; -exports.__esModule = true; //# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Report an error when compiler-options target-script is out-of-range.js b/tests/baselines/reference/transpile/Report an error when compiler-options target-script is out-of-range.js index e9493d9d591..1ceb1bcd146 100644 --- a/tests/baselines/reference/transpile/Report an error when compiler-options target-script is out-of-range.js +++ b/tests/baselines/reference/transpile/Report an error when compiler-options target-script is out-of-range.js @@ -1,3 +1,2 @@ "use strict"; -exports.__esModule = true; //# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Support options with lib values.js b/tests/baselines/reference/transpile/Support options with lib values.js index 72e077de381..36c68f08b9f 100644 --- a/tests/baselines/reference/transpile/Support options with lib values.js +++ b/tests/baselines/reference/transpile/Support options with lib values.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; var a = 10; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Support options with types values.js b/tests/baselines/reference/transpile/Support options with types values.js index 72e077de381..36c68f08b9f 100644 --- a/tests/baselines/reference/transpile/Support options with types values.js +++ b/tests/baselines/reference/transpile/Support options with types values.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; var a = 10; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports backslashes in file name.js b/tests/baselines/reference/transpile/Supports backslashes in file name.js index 8ef38d2b617..942449753b0 100644 --- a/tests/baselines/reference/transpile/Supports backslashes in file name.js +++ b/tests/baselines/reference/transpile/Supports backslashes in file name.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; var x; //# sourceMappingURL=b.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting allowJs.js b/tests/baselines/reference/transpile/Supports setting allowJs.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting allowJs.js +++ b/tests/baselines/reference/transpile/Supports setting allowJs.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting allowSyntheticDefaultImports.js b/tests/baselines/reference/transpile/Supports setting allowSyntheticDefaultImports.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting allowSyntheticDefaultImports.js +++ b/tests/baselines/reference/transpile/Supports setting allowSyntheticDefaultImports.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting allowUnreachableCode.js b/tests/baselines/reference/transpile/Supports setting allowUnreachableCode.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting allowUnreachableCode.js +++ b/tests/baselines/reference/transpile/Supports setting allowUnreachableCode.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting allowUnusedLabels.js b/tests/baselines/reference/transpile/Supports setting allowUnusedLabels.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting allowUnusedLabels.js +++ b/tests/baselines/reference/transpile/Supports setting allowUnusedLabels.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting alwaysStrict.js b/tests/baselines/reference/transpile/Supports setting alwaysStrict.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting alwaysStrict.js +++ b/tests/baselines/reference/transpile/Supports setting alwaysStrict.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting baseUrl.js b/tests/baselines/reference/transpile/Supports setting baseUrl.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting baseUrl.js +++ b/tests/baselines/reference/transpile/Supports setting baseUrl.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting charset.js b/tests/baselines/reference/transpile/Supports setting charset.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting charset.js +++ b/tests/baselines/reference/transpile/Supports setting charset.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting declaration.js b/tests/baselines/reference/transpile/Supports setting declaration.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting declaration.js +++ b/tests/baselines/reference/transpile/Supports setting declaration.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting declarationDir.js b/tests/baselines/reference/transpile/Supports setting declarationDir.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting declarationDir.js +++ b/tests/baselines/reference/transpile/Supports setting declarationDir.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting emitBOM.js b/tests/baselines/reference/transpile/Supports setting emitBOM.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting emitBOM.js +++ b/tests/baselines/reference/transpile/Supports setting emitBOM.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting emitDecoratorMetadata.js b/tests/baselines/reference/transpile/Supports setting emitDecoratorMetadata.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting emitDecoratorMetadata.js +++ b/tests/baselines/reference/transpile/Supports setting emitDecoratorMetadata.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting experimentalDecorators.js b/tests/baselines/reference/transpile/Supports setting experimentalDecorators.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting experimentalDecorators.js +++ b/tests/baselines/reference/transpile/Supports setting experimentalDecorators.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting forceConsistentCasingInFileNames.js b/tests/baselines/reference/transpile/Supports setting forceConsistentCasingInFileNames.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting forceConsistentCasingInFileNames.js +++ b/tests/baselines/reference/transpile/Supports setting forceConsistentCasingInFileNames.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting isolatedModules.js b/tests/baselines/reference/transpile/Supports setting isolatedModules.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting isolatedModules.js +++ b/tests/baselines/reference/transpile/Supports setting isolatedModules.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting jsx.js b/tests/baselines/reference/transpile/Supports setting jsx.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting jsx.js +++ b/tests/baselines/reference/transpile/Supports setting jsx.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting jsxFactory.js b/tests/baselines/reference/transpile/Supports setting jsxFactory.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting jsxFactory.js +++ b/tests/baselines/reference/transpile/Supports setting jsxFactory.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting lib.js b/tests/baselines/reference/transpile/Supports setting lib.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting lib.js +++ b/tests/baselines/reference/transpile/Supports setting lib.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting locale.js b/tests/baselines/reference/transpile/Supports setting locale.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting locale.js +++ b/tests/baselines/reference/transpile/Supports setting locale.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting module.js b/tests/baselines/reference/transpile/Supports setting module.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting module.js +++ b/tests/baselines/reference/transpile/Supports setting module.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting moduleResolution.js b/tests/baselines/reference/transpile/Supports setting moduleResolution.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting moduleResolution.js +++ b/tests/baselines/reference/transpile/Supports setting moduleResolution.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting newLine.js b/tests/baselines/reference/transpile/Supports setting newLine.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting newLine.js +++ b/tests/baselines/reference/transpile/Supports setting newLine.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting noEmit.js b/tests/baselines/reference/transpile/Supports setting noEmit.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting noEmit.js +++ b/tests/baselines/reference/transpile/Supports setting noEmit.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting noEmitHelpers.js b/tests/baselines/reference/transpile/Supports setting noEmitHelpers.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting noEmitHelpers.js +++ b/tests/baselines/reference/transpile/Supports setting noEmitHelpers.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting noEmitOnError.js b/tests/baselines/reference/transpile/Supports setting noEmitOnError.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting noEmitOnError.js +++ b/tests/baselines/reference/transpile/Supports setting noEmitOnError.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting noErrorTruncation.js b/tests/baselines/reference/transpile/Supports setting noErrorTruncation.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting noErrorTruncation.js +++ b/tests/baselines/reference/transpile/Supports setting noErrorTruncation.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting noFallthroughCasesInSwitch.js b/tests/baselines/reference/transpile/Supports setting noFallthroughCasesInSwitch.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting noFallthroughCasesInSwitch.js +++ b/tests/baselines/reference/transpile/Supports setting noFallthroughCasesInSwitch.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting noImplicitAny.js b/tests/baselines/reference/transpile/Supports setting noImplicitAny.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting noImplicitAny.js +++ b/tests/baselines/reference/transpile/Supports setting noImplicitAny.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting noImplicitReturns.js b/tests/baselines/reference/transpile/Supports setting noImplicitReturns.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting noImplicitReturns.js +++ b/tests/baselines/reference/transpile/Supports setting noImplicitReturns.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting noImplicitThis.js b/tests/baselines/reference/transpile/Supports setting noImplicitThis.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting noImplicitThis.js +++ b/tests/baselines/reference/transpile/Supports setting noImplicitThis.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting noImplicitUseStrict.js b/tests/baselines/reference/transpile/Supports setting noImplicitUseStrict.js index 8124d51fde3..8394371f908 100644 --- a/tests/baselines/reference/transpile/Supports setting noImplicitUseStrict.js +++ b/tests/baselines/reference/transpile/Supports setting noImplicitUseStrict.js @@ -1,3 +1,2 @@ -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting noLib.js b/tests/baselines/reference/transpile/Supports setting noLib.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting noLib.js +++ b/tests/baselines/reference/transpile/Supports setting noLib.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting noResolve.js b/tests/baselines/reference/transpile/Supports setting noResolve.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting noResolve.js +++ b/tests/baselines/reference/transpile/Supports setting noResolve.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting out.js b/tests/baselines/reference/transpile/Supports setting out.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting out.js +++ b/tests/baselines/reference/transpile/Supports setting out.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting outDir.js b/tests/baselines/reference/transpile/Supports setting outDir.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting outDir.js +++ b/tests/baselines/reference/transpile/Supports setting outDir.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting outFile.js b/tests/baselines/reference/transpile/Supports setting outFile.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting outFile.js +++ b/tests/baselines/reference/transpile/Supports setting outFile.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting paths.js b/tests/baselines/reference/transpile/Supports setting paths.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting paths.js +++ b/tests/baselines/reference/transpile/Supports setting paths.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting preserveConstEnums.js b/tests/baselines/reference/transpile/Supports setting preserveConstEnums.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting preserveConstEnums.js +++ b/tests/baselines/reference/transpile/Supports setting preserveConstEnums.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting reactNamespace.js b/tests/baselines/reference/transpile/Supports setting reactNamespace.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting reactNamespace.js +++ b/tests/baselines/reference/transpile/Supports setting reactNamespace.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting removeComments.js b/tests/baselines/reference/transpile/Supports setting removeComments.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting removeComments.js +++ b/tests/baselines/reference/transpile/Supports setting removeComments.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting rootDir.js b/tests/baselines/reference/transpile/Supports setting rootDir.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting rootDir.js +++ b/tests/baselines/reference/transpile/Supports setting rootDir.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting rootDirs.js b/tests/baselines/reference/transpile/Supports setting rootDirs.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting rootDirs.js +++ b/tests/baselines/reference/transpile/Supports setting rootDirs.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting skipDefaultLibCheck.js b/tests/baselines/reference/transpile/Supports setting skipDefaultLibCheck.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting skipDefaultLibCheck.js +++ b/tests/baselines/reference/transpile/Supports setting skipDefaultLibCheck.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting skipLibCheck.js b/tests/baselines/reference/transpile/Supports setting skipLibCheck.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting skipLibCheck.js +++ b/tests/baselines/reference/transpile/Supports setting skipLibCheck.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting strictNullChecks.js b/tests/baselines/reference/transpile/Supports setting strictNullChecks.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting strictNullChecks.js +++ b/tests/baselines/reference/transpile/Supports setting strictNullChecks.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting stripInternal.js b/tests/baselines/reference/transpile/Supports setting stripInternal.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting stripInternal.js +++ b/tests/baselines/reference/transpile/Supports setting stripInternal.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting suppressExcessPropertyErrors.js b/tests/baselines/reference/transpile/Supports setting suppressExcessPropertyErrors.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting suppressExcessPropertyErrors.js +++ b/tests/baselines/reference/transpile/Supports setting suppressExcessPropertyErrors.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting suppressImplicitAnyIndexErrors.js b/tests/baselines/reference/transpile/Supports setting suppressImplicitAnyIndexErrors.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting suppressImplicitAnyIndexErrors.js +++ b/tests/baselines/reference/transpile/Supports setting suppressImplicitAnyIndexErrors.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting typeRoots.js b/tests/baselines/reference/transpile/Supports setting typeRoots.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting typeRoots.js +++ b/tests/baselines/reference/transpile/Supports setting typeRoots.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports setting types.js b/tests/baselines/reference/transpile/Supports setting types.js index f960e73bcb8..8d91090453b 100644 --- a/tests/baselines/reference/transpile/Supports setting types.js +++ b/tests/baselines/reference/transpile/Supports setting types.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; x; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Supports urls in file name.js b/tests/baselines/reference/transpile/Supports urls in file name.js index 933981306d2..3923d3c9a41 100644 --- a/tests/baselines/reference/transpile/Supports urls in file name.js +++ b/tests/baselines/reference/transpile/Supports urls in file name.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; var x; //# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Uses correct newLine character.js b/tests/baselines/reference/transpile/Uses correct newLine character.js index 04042012d18..bab9c3c4443 100644 --- a/tests/baselines/reference/transpile/Uses correct newLine character.js +++ b/tests/baselines/reference/transpile/Uses correct newLine character.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; var x = 0; //# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/transpile .js files.js b/tests/baselines/reference/transpile/transpile .js files.js index b9048bd515d..c17099d84ba 100644 --- a/tests/baselines/reference/transpile/transpile .js files.js +++ b/tests/baselines/reference/transpile/transpile .js files.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; var a = 10; //# sourceMappingURL=input.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/transpile file as tsx if jsx is specified.js b/tests/baselines/reference/transpile/transpile file as tsx if jsx is specified.js index 2a73615e476..baa27ee64ce 100644 --- a/tests/baselines/reference/transpile/transpile file as tsx if jsx is specified.js +++ b/tests/baselines/reference/transpile/transpile file as tsx if jsx is specified.js @@ -1,4 +1,3 @@ "use strict"; -exports.__esModule = true; var x = React.createElement("div", null); //# sourceMappingURL=file.js.map \ No newline at end of file From eaca169b114047cb6c663fbbee4ade4b493a031f Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 6 Mar 2017 16:21:54 -0800 Subject: [PATCH 51/65] Remove optionality from the initial type of default-valued parameters When narrowing, remove optionality from the initial type of parameters with initialisers. Note that the type of the initialiser is not used; its presence just means that the initial type of the parameter can't contain undefined. It could contain any other member of a declared union type. --- src/compiler/checker.ts | 43 +++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5d45af57343..f17f079008b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3368,16 +3368,6 @@ namespace ts { return strictNullChecks && optional ? includeFalsyTypes(type, TypeFlags.Undefined) : type; } - /** remove undefined from the annotated type of a parameter when there is an initializer (that doesn't include undefined) */ - function removeOptionalityFromAnnotation(annotatedType: Type, declaration: VariableLikeDeclaration): Type { - const annotationIncludesUndefined = strictNullChecks && - declaration.kind === SyntaxKind.Parameter && - declaration.initializer && - getFalsyFlags(annotatedType) & TypeFlags.Undefined && - !(getFalsyFlags(checkExpression(declaration.initializer)) & TypeFlags.Undefined); - return annotationIncludesUndefined ? getNonNullableType(annotatedType) : annotatedType; - } - // Return the inferred type for a variable, parameter, or property declaration function getTypeForVariableLikeDeclaration(declaration: VariableLikeDeclaration, includeOptionality: boolean): Type { if (declaration.flags & NodeFlags.JavaScriptFile) { @@ -3412,7 +3402,7 @@ namespace ts { // Use type from type annotation if one is present if (declaration.type) { - const declaredType = removeOptionalityFromAnnotation(getTypeFromTypeNode(declaration.type), declaration); + const declaredType = getTypeFromTypeNode(declaration.type); return addOptionality(declaredType, /*optional*/ declaration.questionToken && includeOptionality); } @@ -10248,14 +10238,12 @@ namespace ts { return false; } - function getFlowTypeOfReference(reference: Node, declaredType: Type, assumeInitialized: boolean, flowContainer: Node) { + function isFlowNarrowable(reference: Node, type: Type, couldBeUninitialized?: boolean) { + return reference.flowNode && (type.flags & TypeFlags.Narrowable || couldBeUninitialized); + } + + function getFlowTypeOfReference(reference: Node, declaredType: Type, initialType = declaredType, flowContainer?: Node) { let key: string; - if (!reference.flowNode || assumeInitialized && !(declaredType.flags & TypeFlags.Narrowable)) { - return declaredType; - } - const initialType = assumeInitialized ? declaredType : - declaredType === autoType || declaredType === autoArrayType ? undefinedType : - includeFalsyTypes(declaredType, TypeFlags.Undefined); const visitedFlowStart = visitedFlowCount; const evolvedType = getTypeFromFlowType(getTypeAtFlowNode(reference.flowNode)); visitedFlowCount = visitedFlowStart; @@ -10934,6 +10922,16 @@ namespace ts { return symbol.flags & SymbolFlags.Variable && (getDeclarationNodeFlagsFromSymbol(symbol) & NodeFlags.Const) !== 0 && getTypeOfSymbol(symbol) !== autoArrayType; } + /** remove undefined from the annotated type of a parameter when there is an initializer (that doesn't include undefined) */ + function removeOptionalityFromDeclaredType(declaredType: Type, declaration: VariableLikeDeclaration): Type { + const annotationIncludesUndefined = strictNullChecks && + declaration.kind === SyntaxKind.Parameter && + declaration.initializer && + getFalsyFlags(declaredType) & TypeFlags.Undefined && + !(getFalsyFlags(checkExpression(declaration.initializer)) & TypeFlags.Undefined); + return annotationIncludesUndefined ? getNonNullableType(declaredType) : declaredType; + } + function checkIdentifier(node: Identifier): Type { const symbol = getResolvedSymbol(node); if (symbol === unknownSymbol) { @@ -11052,7 +11050,10 @@ namespace ts { const assumeInitialized = isParameter || isOuterVariable || type !== autoType && type !== autoArrayType && (!strictNullChecks || (type.flags & TypeFlags.Any) !== 0 || isInTypeQuery(node)) || isInAmbientContext(declaration); - const flowType = getFlowTypeOfReference(node, type, assumeInitialized, flowContainer); + const initialType = assumeInitialized ? (isParameter ? removeOptionalityFromDeclaredType(type, getRootDeclaration(declaration) as VariableLikeDeclaration) : type) : + type === autoType || type === autoArrayType ? undefinedType : + includeFalsyTypes(type, TypeFlags.Undefined); + const flowType = isFlowNarrowable(node, type, !assumeInitialized) ? getFlowTypeOfReference(node, type, initialType, flowContainer) : type; // A variable is considered uninitialized when it is possible to analyze the entire control flow graph // from declaration to use, and when the variable's declared type doesn't include undefined but the // control flow based type does include undefined. @@ -11318,7 +11319,7 @@ namespace ts { if (isClassLike(container.parent)) { const symbol = getSymbolOfNode(container.parent); const type = hasModifier(container, ModifierFlags.Static) ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol)).thisType; - return getFlowTypeOfReference(node, type, /*assumeInitialized*/ true, /*flowContainer*/ undefined); + return isFlowNarrowable(node, type) ? getFlowTypeOfReference(node, type) : type; } if (isInJavaScriptFile(node)) { @@ -13309,7 +13310,7 @@ namespace ts { !(prop.flags & SymbolFlags.Method && propType.flags & TypeFlags.Union)) { return propType; } - const flowType = getFlowTypeOfReference(node, propType, /*assumeInitialized*/ true, /*flowContainer*/ undefined); + const flowType = isFlowNarrowable(node, propType) ? getFlowTypeOfReference(node, propType) : propType; return assignmentKind ? getBaseTypeOfLiteralType(flowType) : flowType; } From 533ce824e8235e7545d9d107fe3112c77b6e3cc3 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 6 Mar 2017 16:24:44 -0800 Subject: [PATCH 52/65] Add assignability tests for initialised parameters --- ...ameterAddsUndefinedWithStrictNullChecks.js | 4 ++ ...rAddsUndefinedWithStrictNullChecks.symbols | 40 +++++++++++-------- ...terAddsUndefinedWithStrictNullChecks.types | 12 +++++- ...ameterAddsUndefinedWithStrictNullChecks.ts | 2 + 4 files changed, 41 insertions(+), 17 deletions(-) diff --git a/tests/baselines/reference/defaultParameterAddsUndefinedWithStrictNullChecks.js b/tests/baselines/reference/defaultParameterAddsUndefinedWithStrictNullChecks.js index 329c2fb19ce..7f9cf553fe4 100644 --- a/tests/baselines/reference/defaultParameterAddsUndefinedWithStrictNullChecks.js +++ b/tests/baselines/reference/defaultParameterAddsUndefinedWithStrictNullChecks.js @@ -18,10 +18,12 @@ function foo2(x = "string", b: number) { function foo3(x: string | undefined = "string", b: number) { x.length; // ok, should be string + x = undefined; } function foo4(x: string | undefined = undefined, b: number) { x; // should be string | undefined + x = undefined; } @@ -72,10 +74,12 @@ function foo2(x, b) { function foo3(x, b) { if (x === void 0) { x = "string"; } x.length; // ok, should be string + x = undefined; } function foo4(x, b) { if (x === void 0) { x = undefined; } x; // should be string | undefined + x = undefined; } // .d.ts should have `string | undefined` for foo1, foo2, foo3 and foo4 foo1(undefined, 1); diff --git a/tests/baselines/reference/defaultParameterAddsUndefinedWithStrictNullChecks.symbols b/tests/baselines/reference/defaultParameterAddsUndefinedWithStrictNullChecks.symbols index fb0fce7dc7f..a484377f3f4 100644 --- a/tests/baselines/reference/defaultParameterAddsUndefinedWithStrictNullChecks.symbols +++ b/tests/baselines/reference/defaultParameterAddsUndefinedWithStrictNullChecks.symbols @@ -66,16 +66,24 @@ function foo3(x: string | undefined = "string", b: number) { >x.length : Symbol(String.length, Decl(lib.d.ts, --, --)) >x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 17, 14)) >length : Symbol(String.length, Decl(lib.d.ts, --, --)) + + x = undefined; +>x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 17, 14)) +>undefined : Symbol(undefined) } function foo4(x: string | undefined = undefined, b: number) { ->foo4 : Symbol(foo4, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 19, 1)) ->x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 21, 14)) +>foo4 : Symbol(foo4, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 20, 1)) +>x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 22, 14)) >undefined : Symbol(undefined) ->b : Symbol(b, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 21, 48)) +>b : Symbol(b, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 22, 48)) x; // should be string | undefined ->x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 21, 14)) +>x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 22, 14)) + + x = undefined; +>x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 22, 14)) +>undefined : Symbol(undefined) } @@ -94,40 +102,40 @@ foo3(undefined, 1); >undefined : Symbol(undefined) foo4(undefined, 1); ->foo4 : Symbol(foo4, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 19, 1)) +>foo4 : Symbol(foo4, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 20, 1)) >undefined : Symbol(undefined) function removeUndefinedButNotFalse(x = true) { ->removeUndefinedButNotFalse : Symbol(removeUndefinedButNotFalse, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 31, 19)) ->x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 34, 36)) +>removeUndefinedButNotFalse : Symbol(removeUndefinedButNotFalse, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 33, 19)) +>x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 36, 36)) if (x === false) { ->x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 34, 36)) +>x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 36, 36)) return x; ->x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 34, 36)) +>x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 36, 36)) } } declare const cond: boolean; ->cond : Symbol(cond, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 40, 13)) +>cond : Symbol(cond, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 42, 13)) function removeNothing(y = cond ? true : undefined) { ->removeNothing : Symbol(removeNothing, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 40, 28)) ->y : Symbol(y, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 41, 23)) ->cond : Symbol(cond, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 40, 13)) +>removeNothing : Symbol(removeNothing, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 42, 28)) +>y : Symbol(y, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 43, 23)) +>cond : Symbol(cond, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 42, 13)) >undefined : Symbol(undefined) if (y !== undefined) { ->y : Symbol(y, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 41, 23)) +>y : Symbol(y, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 43, 23)) >undefined : Symbol(undefined) if (y === false) { ->y : Symbol(y, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 41, 23)) +>y : Symbol(y, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 43, 23)) return y; ->y : Symbol(y, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 41, 23)) +>y : Symbol(y, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 43, 23)) } } return true; diff --git a/tests/baselines/reference/defaultParameterAddsUndefinedWithStrictNullChecks.types b/tests/baselines/reference/defaultParameterAddsUndefinedWithStrictNullChecks.types index d95f9259891..54b9cdf2a9b 100644 --- a/tests/baselines/reference/defaultParameterAddsUndefinedWithStrictNullChecks.types +++ b/tests/baselines/reference/defaultParameterAddsUndefinedWithStrictNullChecks.types @@ -86,7 +86,7 @@ function foo2(x = "string", b: number) { function foo3(x: string | undefined = "string", b: number) { >foo3 : (x: string | undefined, b: number) => void ->x : string +>x : string | undefined >"string" : "string" >b : number @@ -94,6 +94,11 @@ function foo3(x: string | undefined = "string", b: number) { >x.length : number >x : string >length : number + + x = undefined; +>x = undefined : undefined +>x : string | undefined +>undefined : undefined } function foo4(x: string | undefined = undefined, b: number) { @@ -104,6 +109,11 @@ function foo4(x: string | undefined = undefined, b: number) { x; // should be string | undefined >x : string | undefined + + x = undefined; +>x = undefined : undefined +>x : string | undefined +>undefined : undefined } diff --git a/tests/cases/compiler/defaultParameterAddsUndefinedWithStrictNullChecks.ts b/tests/cases/compiler/defaultParameterAddsUndefinedWithStrictNullChecks.ts index 8abea19f6cd..04a9e668b32 100644 --- a/tests/cases/compiler/defaultParameterAddsUndefinedWithStrictNullChecks.ts +++ b/tests/cases/compiler/defaultParameterAddsUndefinedWithStrictNullChecks.ts @@ -19,10 +19,12 @@ function foo2(x = "string", b: number) { function foo3(x: string | undefined = "string", b: number) { x.length; // ok, should be string + x = undefined; } function foo4(x: string | undefined = undefined, b: number) { x; // should be string | undefined + x = undefined; } From 8d9692129f42eee650c1b69be98b8a970b79e0e9 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 6 Mar 2017 16:53:39 -0800 Subject: [PATCH 53/65] Fix typo --- 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 aa8d42dd3c1..0db2a792712 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3472,7 +3472,7 @@ namespace ts { return undefined; } - function getWidenedTypeFromJSSpecialPropetyDeclarations(symbol: Symbol) { + function getWidenedTypeFromJSSpecialPropertyDeclarations(symbol: Symbol) { const types: Type[] = []; let definedInConstructor = false; let definedInMethod = false; @@ -3663,7 +3663,7 @@ namespace ts { // * className.prototype.method = expr if (declaration.kind === SyntaxKind.BinaryExpression || declaration.kind === SyntaxKind.PropertyAccessExpression && declaration.parent.kind === SyntaxKind.BinaryExpression) { - type = getWidenedTypeFromJSSpecialPropetyDeclarations(symbol); + type = getWidenedTypeFromJSSpecialPropertyDeclarations(symbol); } else { type = getWidenedTypeForVariableLikeDeclaration(declaration, /*reportErrors*/ true); From 1f46dd9949e3ad3a9d50b324d40cad1db861e851 Mon Sep 17 00:00:00 2001 From: Mike Busyrev Date: Tue, 7 Mar 2017 19:35:57 +0300 Subject: [PATCH 54/65] FIX: #14507 Function parameter default value wrongly emmited by Printer --- src/compiler/emitter.ts | 2 +- src/harness/unittests/printer.ts | 3 +++ .../reference/printerApi/printsFileCorrectly.default.js | 2 ++ .../reference/printerApi/printsFileCorrectly.removeComments.js | 1 + 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index ee224befd45..05b40472c3c 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -819,8 +819,8 @@ namespace ts { writeIfPresent(node.dotDotDotToken, "..."); emit(node.name); writeIfPresent(node.questionToken, "?"); - emitExpressionWithPrefix(" = ", node.initializer); emitWithPrefix(": ", node.type); + emitExpressionWithPrefix(" = ", node.initializer); } function emitDecorator(decorator: Decorator) { diff --git a/src/harness/unittests/printer.ts b/src/harness/unittests/printer.ts index 1a5a5a12f9e..e5167b592c2 100644 --- a/src/harness/unittests/printer.ts +++ b/src/harness/unittests/printer.ts @@ -45,6 +45,9 @@ namespace ts { // comment9 console.log(1 + 2); + + // comment10 + function functionWithDefaultArgValue(argument: string = "defaultValue"): void { } `, ScriptTarget.ES2015); printsCorrectly("default", {}, printer => printer.printFile(sourceFile)); diff --git a/tests/baselines/reference/printerApi/printsFileCorrectly.default.js b/tests/baselines/reference/printerApi/printsFileCorrectly.default.js index 9bff9d656b3..576c8bf68ed 100644 --- a/tests/baselines/reference/printerApi/printsFileCorrectly.default.js +++ b/tests/baselines/reference/printerApi/printsFileCorrectly.default.js @@ -23,3 +23,5 @@ const enum E2 { } // comment9 console.log(1 + 2); +// comment10 +function functionWithDefaultArgValue(argument: string = "defaultValue"): void { } diff --git a/tests/baselines/reference/printerApi/printsFileCorrectly.removeComments.js b/tests/baselines/reference/printerApi/printsFileCorrectly.removeComments.js index b511aff5e78..8e839c069a9 100644 --- a/tests/baselines/reference/printerApi/printsFileCorrectly.removeComments.js +++ b/tests/baselines/reference/printerApi/printsFileCorrectly.removeComments.js @@ -15,3 +15,4 @@ const enum E2 { second } console.log(1 + 2); +function functionWithDefaultArgValue(argument: string = "defaultValue"): void { } From fa02c808d1f3ba554726aa003793fd5ddef92af0 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 7 Mar 2017 09:07:34 -0800 Subject: [PATCH 55/65] Remove null and undefined from contextual 'this' type --- src/compiler/checker.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 04e1f5911cd..22c294d0243 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11601,7 +11601,7 @@ namespace ts { } } } - if (compilerOptions.noImplicitThis) { + if (noImplicitThis) { const containingLiteral = getContainingObjectLiteral(func); if (containingLiteral) { // We have an object literal method. Check if the containing object literal has a contextual type @@ -11622,9 +11622,9 @@ namespace ts { type = getApparentTypeOfContextualType(literal); } // There was no contextual ThisType for the containing object literal, so the contextual type - // for 'this' is the contextual type for the containing object literal or the type of the object - // literal itself. - return contextualType || checkExpressionCached(containingLiteral); + // for 'this' is the non-null form of the contextual type for the containing object literal or + // the type of the object literal itself. + return contextualType ? getNonNullableType(contextualType) : checkExpressionCached(containingLiteral); } // In an assignment of the form 'obj.xxx = function(...)' or 'obj[xxx] = function(...)', the // contextual type for 'this' is 'obj'. From 0ac92b47065b4cce27aea38b932f123c6f8aa8fa Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 7 Mar 2017 09:07:53 -0800 Subject: [PATCH 56/65] Add tests --- .../thisType/thisTypeInObjectLiterals2.ts | 54 +++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals2.ts b/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals2.ts index d476679aef1..27861f81da6 100644 --- a/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals2.ts +++ b/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals2.ts @@ -1,7 +1,5 @@ // @declaration: true -// @strictNullChecks: true -// @noImplicitAny: true -// @noImplicitThis: true +// @strict: true // @target: es5 // In methods of an object literal with no contextual type, 'this' has the type @@ -51,6 +49,42 @@ let p1: Point = { } }; +let p2: Point | null = { + x: 10, + y: 20, + moveBy(dx, dy, dz) { + this.x += dx; + this.y += dy; + if (this.z && dz) { + this.z += dz; + } + } +}; + +let p3: Point | undefined = { + x: 10, + y: 20, + moveBy(dx, dy, dz) { + this.x += dx; + this.y += dy; + if (this.z && dz) { + this.z += dz; + } + } +}; + +let p4: Point | null | undefined = { + x: 10, + y: 20, + moveBy(dx, dy, dz) { + this.x += dx; + this.y += dy; + if (this.z && dz) { + this.z += dz; + } + } +}; + declare function f1(p: Point): void; f1({ @@ -65,6 +99,20 @@ f1({ } }); +declare function f2(p: Point | null | undefined): void; + +f2({ + x: 10, + y: 20, + moveBy(dx, dy, dz) { + this.x += dx; + this.y += dy; + if (this.z && dz) { + this.z += dz; + } + } +}); + // In methods of an object literal with a contextual type that includes some // ThisType, 'this' is of type T. From a4d2c572bf4b8387c565d10c26e8b25b73783bf9 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Tue, 7 Mar 2017 09:08:02 -0800 Subject: [PATCH 57/65] Accept new baselines --- .../reference/thisTypeInObjectLiterals2.js | 99 +++ .../thisTypeInObjectLiterals2.symbols | 648 +++++++++++------- .../reference/thisTypeInObjectLiterals2.types | 208 ++++++ 3 files changed, 719 insertions(+), 236 deletions(-) diff --git a/tests/baselines/reference/thisTypeInObjectLiterals2.js b/tests/baselines/reference/thisTypeInObjectLiterals2.js index 88cbd2555f6..a9b666fda8f 100644 --- a/tests/baselines/reference/thisTypeInObjectLiterals2.js +++ b/tests/baselines/reference/thisTypeInObjectLiterals2.js @@ -47,6 +47,42 @@ let p1: Point = { } }; +let p2: Point | null = { + x: 10, + y: 20, + moveBy(dx, dy, dz) { + this.x += dx; + this.y += dy; + if (this.z && dz) { + this.z += dz; + } + } +}; + +let p3: Point | undefined = { + x: 10, + y: 20, + moveBy(dx, dy, dz) { + this.x += dx; + this.y += dy; + if (this.z && dz) { + this.z += dz; + } + } +}; + +let p4: Point | null | undefined = { + x: 10, + y: 20, + moveBy(dx, dy, dz) { + this.x += dx; + this.y += dy; + if (this.z && dz) { + this.z += dz; + } + } +}; + declare function f1(p: Point): void; f1({ @@ -61,6 +97,20 @@ f1({ } }); +declare function f2(p: Point | null | undefined): void; + +f2({ + x: 10, + y: 20, + moveBy(dx, dy, dz) { + this.x += dx; + this.y += dy; + if (this.z && dz) { + this.z += dz; + } + } +}); + // In methods of an object literal with a contextual type that includes some // ThisType, 'this' is of type T. @@ -196,6 +246,7 @@ vue.hello; //// [thisTypeInObjectLiterals2.js] // In methods of an object literal with no contextual type, 'this' has the type // of the object literal. +"use strict"; var obj1 = { a: 1, f: function () { @@ -228,6 +279,39 @@ var p1 = { } } }; +var p2 = { + x: 10, + y: 20, + moveBy: function (dx, dy, dz) { + this.x += dx; + this.y += dy; + if (this.z && dz) { + this.z += dz; + } + } +}; +var p3 = { + x: 10, + y: 20, + moveBy: function (dx, dy, dz) { + this.x += dx; + this.y += dy; + if (this.z && dz) { + this.z += dz; + } + } +}; +var p4 = { + x: 10, + y: 20, + moveBy: function (dx, dy, dz) { + this.x += dx; + this.y += dy; + if (this.z && dz) { + this.z += dz; + } + } +}; f1({ x: 10, y: 20, @@ -239,6 +323,17 @@ f1({ } } }); +f2({ + x: 10, + y: 20, + moveBy: function (dx, dy, dz) { + this.x += dx; + this.y += dy; + if (this.z && dz) { + this.z += dz; + } + } +}); var x1 = makeObject({ data: { x: 0, y: 0 }, methods: { @@ -328,7 +423,11 @@ declare type Point = { moveBy(dx: number, dy: number, dz?: number): void; }; declare let p1: Point; +declare let p2: Point | null; +declare let p3: Point | undefined; +declare let p4: Point | null | undefined; declare function f1(p: Point): void; +declare function f2(p: Point | null | undefined): void; declare type ObjectDescriptor = { data?: D; methods?: M & ThisType; diff --git a/tests/baselines/reference/thisTypeInObjectLiterals2.symbols b/tests/baselines/reference/thisTypeInObjectLiterals2.symbols index e7412ab487f..4c3e60c7536 100644 --- a/tests/baselines/reference/thisTypeInObjectLiterals2.symbols +++ b/tests/baselines/reference/thisTypeInObjectLiterals2.symbols @@ -128,49 +128,225 @@ let p1: Point = { } }; -declare function f1(p: Point): void; ->f1 : Symbol(f1, Decl(thisTypeInObjectLiterals2.ts, 46, 2)) ->p : Symbol(p, Decl(thisTypeInObjectLiterals2.ts, 48, 20)) +let p2: Point | null = { +>p2 : Symbol(p2, Decl(thisTypeInObjectLiterals2.ts, 48, 3)) >Point : Symbol(Point, Decl(thisTypeInObjectLiterals2.ts, 24, 2)) -f1({ ->f1 : Symbol(f1, Decl(thisTypeInObjectLiterals2.ts, 46, 2)) - x: 10, ->x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 50, 4)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 48, 24)) y: 20, ->y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 51, 10)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 49, 10)) moveBy(dx, dy, dz) { ->moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 52, 10)) ->dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 53, 11)) ->dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 53, 14)) ->dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 53, 18)) +>moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 50, 10)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 51, 11)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 51, 14)) +>dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 51, 18)) this.x += dx; >this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) >this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) >x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) ->dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 53, 11)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 51, 11)) this.y += dy; >this.y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14)) >this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) >y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14)) ->dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 53, 14)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 51, 14)) if (this.z && dz) { >this.z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) >this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) >z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) ->dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 53, 18)) +>dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 51, 18)) this.z += dz; >this.z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) >this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) >z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) ->dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 53, 18)) +>dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 51, 18)) + } + } +}; + +let p3: Point | undefined = { +>p3 : Symbol(p3, Decl(thisTypeInObjectLiterals2.ts, 60, 3)) +>Point : Symbol(Point, Decl(thisTypeInObjectLiterals2.ts, 24, 2)) + + x: 10, +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 60, 29)) + + y: 20, +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 61, 10)) + + moveBy(dx, dy, dz) { +>moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 62, 10)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 63, 11)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 63, 14)) +>dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 63, 18)) + + this.x += dx; +>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 63, 11)) + + this.y += dy; +>this.y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 63, 14)) + + if (this.z && dz) { +>this.z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) +>dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 63, 18)) + + this.z += dz; +>this.z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) +>dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 63, 18)) + } + } +}; + +let p4: Point | null | undefined = { +>p4 : Symbol(p4, Decl(thisTypeInObjectLiterals2.ts, 72, 3)) +>Point : Symbol(Point, Decl(thisTypeInObjectLiterals2.ts, 24, 2)) + + x: 10, +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 72, 36)) + + y: 20, +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 73, 10)) + + moveBy(dx, dy, dz) { +>moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 74, 10)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 75, 11)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 75, 14)) +>dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 75, 18)) + + this.x += dx; +>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 75, 11)) + + this.y += dy; +>this.y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 75, 14)) + + if (this.z && dz) { +>this.z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) +>dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 75, 18)) + + this.z += dz; +>this.z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) +>dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 75, 18)) + } + } +}; + +declare function f1(p: Point): void; +>f1 : Symbol(f1, Decl(thisTypeInObjectLiterals2.ts, 82, 2)) +>p : Symbol(p, Decl(thisTypeInObjectLiterals2.ts, 84, 20)) +>Point : Symbol(Point, Decl(thisTypeInObjectLiterals2.ts, 24, 2)) + +f1({ +>f1 : Symbol(f1, Decl(thisTypeInObjectLiterals2.ts, 82, 2)) + + x: 10, +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 86, 4)) + + y: 20, +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 87, 10)) + + moveBy(dx, dy, dz) { +>moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 88, 10)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 89, 11)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 89, 14)) +>dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 89, 18)) + + this.x += dx; +>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 89, 11)) + + this.y += dy; +>this.y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 89, 14)) + + if (this.z && dz) { +>this.z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) +>dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 89, 18)) + + this.z += dz; +>this.z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) +>dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 89, 18)) + } + } +}); + +declare function f2(p: Point | null | undefined): void; +>f2 : Symbol(f2, Decl(thisTypeInObjectLiterals2.ts, 96, 3)) +>p : Symbol(p, Decl(thisTypeInObjectLiterals2.ts, 98, 20)) +>Point : Symbol(Point, Decl(thisTypeInObjectLiterals2.ts, 24, 2)) + +f2({ +>f2 : Symbol(f2, Decl(thisTypeInObjectLiterals2.ts, 96, 3)) + + x: 10, +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 100, 4)) + + y: 20, +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 101, 10)) + + moveBy(dx, dy, dz) { +>moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 102, 10)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 103, 11)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 103, 14)) +>dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 103, 18)) + + this.x += dx; +>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 103, 11)) + + this.y += dy; +>this.y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 30, 14)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 103, 14)) + + if (this.z && dz) { +>this.z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) +>dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 103, 18)) + + this.z += dz; +>this.z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) +>this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) +>z : Symbol(z, Decl(thisTypeInObjectLiterals2.ts, 31, 14)) +>dz : Symbol(dz, Decl(thisTypeInObjectLiterals2.ts, 103, 18)) } } }); @@ -179,59 +355,59 @@ f1({ // ThisType, 'this' is of type T. type ObjectDescriptor = { ->ObjectDescriptor : Symbol(ObjectDescriptor, Decl(thisTypeInObjectLiterals2.ts, 60, 3)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 65, 22)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 65, 24)) +>ObjectDescriptor : Symbol(ObjectDescriptor, Decl(thisTypeInObjectLiterals2.ts, 110, 3)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 115, 22)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 115, 24)) data?: D; ->data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 65, 31)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 65, 22)) +>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 115, 31)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 115, 22)) methods?: M & ThisType; // Type of 'this' in methods is D & M ->methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 66, 13)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 65, 24)) +>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 116, 13)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 115, 24)) >ThisType : Symbol(ThisType, Decl(lib.d.ts, --, --)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 65, 22)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 65, 24)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 115, 22)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 115, 24)) } declare function makeObject(desc: ObjectDescriptor): D & M; ->makeObject : Symbol(makeObject, Decl(thisTypeInObjectLiterals2.ts, 68, 1)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 70, 28)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 70, 30)) ->desc : Symbol(desc, Decl(thisTypeInObjectLiterals2.ts, 70, 34)) ->ObjectDescriptor : Symbol(ObjectDescriptor, Decl(thisTypeInObjectLiterals2.ts, 60, 3)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 70, 28)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 70, 30)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 70, 28)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 70, 30)) +>makeObject : Symbol(makeObject, Decl(thisTypeInObjectLiterals2.ts, 118, 1)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 120, 28)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 120, 30)) +>desc : Symbol(desc, Decl(thisTypeInObjectLiterals2.ts, 120, 34)) +>ObjectDescriptor : Symbol(ObjectDescriptor, Decl(thisTypeInObjectLiterals2.ts, 110, 3)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 120, 28)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 120, 30)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 120, 28)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 120, 30)) let x1 = makeObject({ ->x1 : Symbol(x1, Decl(thisTypeInObjectLiterals2.ts, 72, 3)) ->makeObject : Symbol(makeObject, Decl(thisTypeInObjectLiterals2.ts, 68, 1)) +>x1 : Symbol(x1, Decl(thisTypeInObjectLiterals2.ts, 122, 3)) +>makeObject : Symbol(makeObject, Decl(thisTypeInObjectLiterals2.ts, 118, 1)) data: { x: 0, y: 0 }, ->data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 72, 21)) ->x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 73, 11)) ->y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 73, 17)) +>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 122, 21)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 123, 11)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 123, 17)) methods: { ->methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 73, 25)) +>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 123, 25)) moveBy(dx: number, dy: number) { ->moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 74, 14)) ->dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 75, 15)) ->dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 75, 26)) +>moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 124, 14)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 125, 15)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 125, 26)) this.x += dx; // Strongly typed this ->this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 73, 11)) ->x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 73, 11)) ->dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 75, 15)) +>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 123, 11)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 123, 11)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 125, 15)) this.y += dy; // Strongly typed this ->this.y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 73, 17)) ->y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 73, 17)) ->dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 75, 26)) +>this.y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 123, 17)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 123, 17)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 125, 26)) } } }); @@ -240,59 +416,59 @@ let x1 = makeObject({ // some ThisType, 'this' is of type T. type ObjectDescriptor2 = ThisType & { ->ObjectDescriptor2 : Symbol(ObjectDescriptor2, Decl(thisTypeInObjectLiterals2.ts, 80, 3)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 85, 23)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 85, 25)) +>ObjectDescriptor2 : Symbol(ObjectDescriptor2, Decl(thisTypeInObjectLiterals2.ts, 130, 3)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 135, 23)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 135, 25)) >ThisType : Symbol(ThisType, Decl(lib.d.ts, --, --)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 85, 23)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 85, 25)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 135, 23)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 135, 25)) data?: D; ->data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 85, 50)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 85, 23)) +>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 135, 50)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 135, 23)) methods?: M; ->methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 86, 13)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 85, 25)) +>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 136, 13)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 135, 25)) } declare function makeObject2(desc: ObjectDescriptor): D & M; ->makeObject2 : Symbol(makeObject2, Decl(thisTypeInObjectLiterals2.ts, 88, 1)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 90, 29)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 90, 31)) ->desc : Symbol(desc, Decl(thisTypeInObjectLiterals2.ts, 90, 35)) ->ObjectDescriptor : Symbol(ObjectDescriptor, Decl(thisTypeInObjectLiterals2.ts, 60, 3)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 90, 29)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 90, 31)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 90, 29)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 90, 31)) +>makeObject2 : Symbol(makeObject2, Decl(thisTypeInObjectLiterals2.ts, 138, 1)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 140, 29)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 140, 31)) +>desc : Symbol(desc, Decl(thisTypeInObjectLiterals2.ts, 140, 35)) +>ObjectDescriptor : Symbol(ObjectDescriptor, Decl(thisTypeInObjectLiterals2.ts, 110, 3)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 140, 29)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 140, 31)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 140, 29)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 140, 31)) let x2 = makeObject2({ ->x2 : Symbol(x2, Decl(thisTypeInObjectLiterals2.ts, 92, 3)) ->makeObject2 : Symbol(makeObject2, Decl(thisTypeInObjectLiterals2.ts, 88, 1)) +>x2 : Symbol(x2, Decl(thisTypeInObjectLiterals2.ts, 142, 3)) +>makeObject2 : Symbol(makeObject2, Decl(thisTypeInObjectLiterals2.ts, 138, 1)) data: { x: 0, y: 0 }, ->data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 92, 22)) ->x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 93, 11)) ->y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 93, 17)) +>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 142, 22)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 143, 11)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 143, 17)) methods: { ->methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 93, 25)) +>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 143, 25)) moveBy(dx: number, dy: number) { ->moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 94, 14)) ->dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 95, 15)) ->dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 95, 26)) +>moveBy : Symbol(moveBy, Decl(thisTypeInObjectLiterals2.ts, 144, 14)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 145, 15)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 145, 26)) this.x += dx; // Strongly typed this ->this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 93, 11)) ->x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 93, 11)) ->dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 95, 15)) +>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 143, 11)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 143, 11)) +>dx : Symbol(dx, Decl(thisTypeInObjectLiterals2.ts, 145, 15)) this.y += dy; // Strongly typed this ->this.y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 93, 17)) ->y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 93, 17)) ->dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 95, 26)) +>this.y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 143, 17)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 143, 17)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 145, 26)) } } }); @@ -300,89 +476,89 @@ let x2 = makeObject2({ // Check pattern similar to Object.defineProperty and Object.defineProperties type PropDesc = { ->PropDesc : Symbol(PropDesc, Decl(thisTypeInObjectLiterals2.ts, 100, 3)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 104, 14)) +>PropDesc : Symbol(PropDesc, Decl(thisTypeInObjectLiterals2.ts, 150, 3)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 154, 14)) value?: T; ->value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 104, 20)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 104, 14)) +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 154, 20)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 154, 14)) get?(): T; ->get : Symbol(get, Decl(thisTypeInObjectLiterals2.ts, 105, 14)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 104, 14)) +>get : Symbol(get, Decl(thisTypeInObjectLiterals2.ts, 155, 14)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 154, 14)) set?(value: T): void; ->set : Symbol(set, Decl(thisTypeInObjectLiterals2.ts, 106, 14)) ->value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 107, 9)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 104, 14)) +>set : Symbol(set, Decl(thisTypeInObjectLiterals2.ts, 156, 14)) +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 157, 9)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 154, 14)) } type PropDescMap = { ->PropDescMap : Symbol(PropDescMap, Decl(thisTypeInObjectLiterals2.ts, 108, 1)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 110, 17)) +>PropDescMap : Symbol(PropDescMap, Decl(thisTypeInObjectLiterals2.ts, 158, 1)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 160, 17)) [K in keyof T]: PropDesc; ->K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 111, 5)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 110, 17)) ->PropDesc : Symbol(PropDesc, Decl(thisTypeInObjectLiterals2.ts, 100, 3)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 110, 17)) ->K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 111, 5)) +>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 161, 5)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 160, 17)) +>PropDesc : Symbol(PropDesc, Decl(thisTypeInObjectLiterals2.ts, 150, 3)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 160, 17)) +>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 161, 5)) } declare function defineProp(obj: T, name: K, desc: PropDesc & ThisType): T & Record; ->defineProp : Symbol(defineProp, Decl(thisTypeInObjectLiterals2.ts, 112, 1)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 114, 28)) ->K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 114, 30)) ->U : Symbol(U, Decl(thisTypeInObjectLiterals2.ts, 114, 48)) ->obj : Symbol(obj, Decl(thisTypeInObjectLiterals2.ts, 114, 52)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 114, 28)) ->name : Symbol(name, Decl(thisTypeInObjectLiterals2.ts, 114, 59)) ->K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 114, 30)) ->desc : Symbol(desc, Decl(thisTypeInObjectLiterals2.ts, 114, 68)) ->PropDesc : Symbol(PropDesc, Decl(thisTypeInObjectLiterals2.ts, 100, 3)) ->U : Symbol(U, Decl(thisTypeInObjectLiterals2.ts, 114, 48)) +>defineProp : Symbol(defineProp, Decl(thisTypeInObjectLiterals2.ts, 162, 1)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 164, 28)) +>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 164, 30)) +>U : Symbol(U, Decl(thisTypeInObjectLiterals2.ts, 164, 48)) +>obj : Symbol(obj, Decl(thisTypeInObjectLiterals2.ts, 164, 52)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 164, 28)) +>name : Symbol(name, Decl(thisTypeInObjectLiterals2.ts, 164, 59)) +>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 164, 30)) +>desc : Symbol(desc, Decl(thisTypeInObjectLiterals2.ts, 164, 68)) +>PropDesc : Symbol(PropDesc, Decl(thisTypeInObjectLiterals2.ts, 150, 3)) +>U : Symbol(U, Decl(thisTypeInObjectLiterals2.ts, 164, 48)) >ThisType : Symbol(ThisType, Decl(lib.d.ts, --, --)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 114, 28)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 114, 28)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 164, 28)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 164, 28)) >Record : Symbol(Record, Decl(lib.d.ts, --, --)) ->K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 114, 30)) ->U : Symbol(U, Decl(thisTypeInObjectLiterals2.ts, 114, 48)) +>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 164, 30)) +>U : Symbol(U, Decl(thisTypeInObjectLiterals2.ts, 164, 48)) declare function defineProps(obj: T, descs: PropDescMap & ThisType): T & U; ->defineProps : Symbol(defineProps, Decl(thisTypeInObjectLiterals2.ts, 114, 120)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 116, 29)) ->U : Symbol(U, Decl(thisTypeInObjectLiterals2.ts, 116, 31)) ->obj : Symbol(obj, Decl(thisTypeInObjectLiterals2.ts, 116, 35)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 116, 29)) ->descs : Symbol(descs, Decl(thisTypeInObjectLiterals2.ts, 116, 42)) ->PropDescMap : Symbol(PropDescMap, Decl(thisTypeInObjectLiterals2.ts, 108, 1)) ->U : Symbol(U, Decl(thisTypeInObjectLiterals2.ts, 116, 31)) +>defineProps : Symbol(defineProps, Decl(thisTypeInObjectLiterals2.ts, 164, 120)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 166, 29)) +>U : Symbol(U, Decl(thisTypeInObjectLiterals2.ts, 166, 31)) +>obj : Symbol(obj, Decl(thisTypeInObjectLiterals2.ts, 166, 35)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 166, 29)) +>descs : Symbol(descs, Decl(thisTypeInObjectLiterals2.ts, 166, 42)) +>PropDescMap : Symbol(PropDescMap, Decl(thisTypeInObjectLiterals2.ts, 158, 1)) +>U : Symbol(U, Decl(thisTypeInObjectLiterals2.ts, 166, 31)) >ThisType : Symbol(ThisType, Decl(lib.d.ts, --, --)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 116, 29)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 116, 29)) ->U : Symbol(U, Decl(thisTypeInObjectLiterals2.ts, 116, 31)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 166, 29)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 166, 29)) +>U : Symbol(U, Decl(thisTypeInObjectLiterals2.ts, 166, 31)) let p10 = defineProp(p1, "foo", { value: 42 }); ->p10 : Symbol(p10, Decl(thisTypeInObjectLiterals2.ts, 118, 3)) ->defineProp : Symbol(defineProp, Decl(thisTypeInObjectLiterals2.ts, 112, 1)) +>p10 : Symbol(p10, Decl(thisTypeInObjectLiterals2.ts, 168, 3)) +>defineProp : Symbol(defineProp, Decl(thisTypeInObjectLiterals2.ts, 162, 1)) >p1 : Symbol(p1, Decl(thisTypeInObjectLiterals2.ts, 36, 3)) ->value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 118, 33)) +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 168, 33)) p10.foo = p10.foo + 1; >p10.foo : Symbol(foo) ->p10 : Symbol(p10, Decl(thisTypeInObjectLiterals2.ts, 118, 3)) +>p10 : Symbol(p10, Decl(thisTypeInObjectLiterals2.ts, 168, 3)) >foo : Symbol(foo) >p10.foo : Symbol(foo) ->p10 : Symbol(p10, Decl(thisTypeInObjectLiterals2.ts, 118, 3)) +>p10 : Symbol(p10, Decl(thisTypeInObjectLiterals2.ts, 168, 3)) >foo : Symbol(foo) let p11 = defineProp(p1, "bar", { ->p11 : Symbol(p11, Decl(thisTypeInObjectLiterals2.ts, 121, 3)) ->defineProp : Symbol(defineProp, Decl(thisTypeInObjectLiterals2.ts, 112, 1)) +>p11 : Symbol(p11, Decl(thisTypeInObjectLiterals2.ts, 171, 3)) +>defineProp : Symbol(defineProp, Decl(thisTypeInObjectLiterals2.ts, 162, 1)) >p1 : Symbol(p1, Decl(thisTypeInObjectLiterals2.ts, 36, 3)) get() { ->get : Symbol(get, Decl(thisTypeInObjectLiterals2.ts, 121, 33)) +>get : Symbol(get, Decl(thisTypeInObjectLiterals2.ts, 171, 33)) return this.x; >this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) @@ -391,41 +567,41 @@ let p11 = defineProp(p1, "bar", { }, set(value: number) { ->set : Symbol(set, Decl(thisTypeInObjectLiterals2.ts, 124, 6)) ->value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 125, 8)) +>set : Symbol(set, Decl(thisTypeInObjectLiterals2.ts, 174, 6)) +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 175, 8)) this.x = value; >this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) >this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) >x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) ->value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 125, 8)) +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 175, 8)) } }); p11.bar = p11.bar + 1; >p11.bar : Symbol(bar) ->p11 : Symbol(p11, Decl(thisTypeInObjectLiterals2.ts, 121, 3)) +>p11 : Symbol(p11, Decl(thisTypeInObjectLiterals2.ts, 171, 3)) >bar : Symbol(bar) >p11.bar : Symbol(bar) ->p11 : Symbol(p11, Decl(thisTypeInObjectLiterals2.ts, 121, 3)) +>p11 : Symbol(p11, Decl(thisTypeInObjectLiterals2.ts, 171, 3)) >bar : Symbol(bar) let p12 = defineProps(p1, { ->p12 : Symbol(p12, Decl(thisTypeInObjectLiterals2.ts, 131, 3)) ->defineProps : Symbol(defineProps, Decl(thisTypeInObjectLiterals2.ts, 114, 120)) +>p12 : Symbol(p12, Decl(thisTypeInObjectLiterals2.ts, 181, 3)) +>defineProps : Symbol(defineProps, Decl(thisTypeInObjectLiterals2.ts, 164, 120)) >p1 : Symbol(p1, Decl(thisTypeInObjectLiterals2.ts, 36, 3)) foo: { ->foo : Symbol(foo, Decl(thisTypeInObjectLiterals2.ts, 131, 27)) +>foo : Symbol(foo, Decl(thisTypeInObjectLiterals2.ts, 181, 27)) value: 42 ->value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 132, 10)) +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 182, 10)) }, bar: { ->bar : Symbol(bar, Decl(thisTypeInObjectLiterals2.ts, 134, 6)) +>bar : Symbol(bar, Decl(thisTypeInObjectLiterals2.ts, 184, 6)) get(): number { ->get : Symbol(get, Decl(thisTypeInObjectLiterals2.ts, 135, 10)) +>get : Symbol(get, Decl(thisTypeInObjectLiterals2.ts, 185, 10)) return this.x; >this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) @@ -434,173 +610,173 @@ let p12 = defineProps(p1, { }, set(value: number) { ->set : Symbol(set, Decl(thisTypeInObjectLiterals2.ts, 138, 10)) ->value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 139, 12)) +>set : Symbol(set, Decl(thisTypeInObjectLiterals2.ts, 188, 10)) +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 189, 12)) this.x = value; >this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) >this : Symbol(__type, Decl(thisTypeInObjectLiterals2.ts, 29, 12)) >x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 29, 14)) ->value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 139, 12)) +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 189, 12)) } } }); p12.foo = p12.foo + 1; ->p12.foo : Symbol(foo, Decl(thisTypeInObjectLiterals2.ts, 131, 27)) ->p12 : Symbol(p12, Decl(thisTypeInObjectLiterals2.ts, 131, 3)) ->foo : Symbol(foo, Decl(thisTypeInObjectLiterals2.ts, 131, 27)) ->p12.foo : Symbol(foo, Decl(thisTypeInObjectLiterals2.ts, 131, 27)) ->p12 : Symbol(p12, Decl(thisTypeInObjectLiterals2.ts, 131, 3)) ->foo : Symbol(foo, Decl(thisTypeInObjectLiterals2.ts, 131, 27)) +>p12.foo : Symbol(foo, Decl(thisTypeInObjectLiterals2.ts, 181, 27)) +>p12 : Symbol(p12, Decl(thisTypeInObjectLiterals2.ts, 181, 3)) +>foo : Symbol(foo, Decl(thisTypeInObjectLiterals2.ts, 181, 27)) +>p12.foo : Symbol(foo, Decl(thisTypeInObjectLiterals2.ts, 181, 27)) +>p12 : Symbol(p12, Decl(thisTypeInObjectLiterals2.ts, 181, 3)) +>foo : Symbol(foo, Decl(thisTypeInObjectLiterals2.ts, 181, 27)) p12.bar = p12.bar + 1; ->p12.bar : Symbol(bar, Decl(thisTypeInObjectLiterals2.ts, 134, 6)) ->p12 : Symbol(p12, Decl(thisTypeInObjectLiterals2.ts, 131, 3)) ->bar : Symbol(bar, Decl(thisTypeInObjectLiterals2.ts, 134, 6)) ->p12.bar : Symbol(bar, Decl(thisTypeInObjectLiterals2.ts, 134, 6)) ->p12 : Symbol(p12, Decl(thisTypeInObjectLiterals2.ts, 131, 3)) ->bar : Symbol(bar, Decl(thisTypeInObjectLiterals2.ts, 134, 6)) +>p12.bar : Symbol(bar, Decl(thisTypeInObjectLiterals2.ts, 184, 6)) +>p12 : Symbol(p12, Decl(thisTypeInObjectLiterals2.ts, 181, 3)) +>bar : Symbol(bar, Decl(thisTypeInObjectLiterals2.ts, 184, 6)) +>p12.bar : Symbol(bar, Decl(thisTypeInObjectLiterals2.ts, 184, 6)) +>p12 : Symbol(p12, Decl(thisTypeInObjectLiterals2.ts, 181, 3)) +>bar : Symbol(bar, Decl(thisTypeInObjectLiterals2.ts, 184, 6)) // Proof of concept for typing of Vue.js type Accessors = { [K in keyof T]: (() => T[K]) | Computed }; ->Accessors : Symbol(Accessors, Decl(thisTypeInObjectLiterals2.ts, 145, 22)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 149, 15)) ->K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 149, 23)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 149, 15)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 149, 15)) ->K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 149, 23)) ->Computed : Symbol(Computed, Decl(thisTypeInObjectLiterals2.ts, 151, 39)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 149, 15)) ->K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 149, 23)) +>Accessors : Symbol(Accessors, Decl(thisTypeInObjectLiterals2.ts, 195, 22)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 199, 15)) +>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 199, 23)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 199, 15)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 199, 15)) +>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 199, 23)) +>Computed : Symbol(Computed, Decl(thisTypeInObjectLiterals2.ts, 201, 39)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 199, 15)) +>K : Symbol(K, Decl(thisTypeInObjectLiterals2.ts, 199, 23)) type Dictionary = { [x: string]: T } ->Dictionary : Symbol(Dictionary, Decl(thisTypeInObjectLiterals2.ts, 149, 70)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 151, 16)) ->x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 151, 24)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 151, 16)) +>Dictionary : Symbol(Dictionary, Decl(thisTypeInObjectLiterals2.ts, 199, 70)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 201, 16)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 201, 24)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 201, 16)) type Computed = { ->Computed : Symbol(Computed, Decl(thisTypeInObjectLiterals2.ts, 151, 39)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 153, 14)) +>Computed : Symbol(Computed, Decl(thisTypeInObjectLiterals2.ts, 201, 39)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 203, 14)) get?(): T; ->get : Symbol(get, Decl(thisTypeInObjectLiterals2.ts, 153, 20)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 153, 14)) +>get : Symbol(get, Decl(thisTypeInObjectLiterals2.ts, 203, 20)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 203, 14)) set?(value: T): void; ->set : Symbol(set, Decl(thisTypeInObjectLiterals2.ts, 154, 14)) ->value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 155, 9)) ->T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 153, 14)) +>set : Symbol(set, Decl(thisTypeInObjectLiterals2.ts, 204, 14)) +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 205, 9)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 203, 14)) } type VueOptions = ThisType & { ->VueOptions : Symbol(VueOptions, Decl(thisTypeInObjectLiterals2.ts, 156, 1)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 158, 16)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 158, 18)) ->P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 158, 21)) +>VueOptions : Symbol(VueOptions, Decl(thisTypeInObjectLiterals2.ts, 206, 1)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 208, 16)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 208, 18)) +>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 208, 21)) >ThisType : Symbol(ThisType, Decl(lib.d.ts, --, --)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 158, 16)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 158, 18)) ->P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 158, 21)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 208, 16)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 208, 18)) +>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 208, 21)) data?: D | (() => D); ->data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 158, 50)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 158, 16)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 158, 16)) +>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 208, 50)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 208, 16)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 208, 16)) methods?: M; ->methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 159, 25)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 158, 18)) +>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 209, 25)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 208, 18)) computed?: Accessors

; ->computed : Symbol(computed, Decl(thisTypeInObjectLiterals2.ts, 160, 16)) ->Accessors : Symbol(Accessors, Decl(thisTypeInObjectLiterals2.ts, 145, 22)) ->P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 158, 21)) +>computed : Symbol(computed, Decl(thisTypeInObjectLiterals2.ts, 210, 16)) +>Accessors : Symbol(Accessors, Decl(thisTypeInObjectLiterals2.ts, 195, 22)) +>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 208, 21)) } declare const Vue: new (options: VueOptions) => D & M & P; ->Vue : Symbol(Vue, Decl(thisTypeInObjectLiterals2.ts, 164, 13)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 164, 24)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 164, 26)) ->P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 164, 29)) ->options : Symbol(options, Decl(thisTypeInObjectLiterals2.ts, 164, 33)) ->VueOptions : Symbol(VueOptions, Decl(thisTypeInObjectLiterals2.ts, 156, 1)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 164, 24)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 164, 26)) ->P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 164, 29)) ->D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 164, 24)) ->M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 164, 26)) ->P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 164, 29)) +>Vue : Symbol(Vue, Decl(thisTypeInObjectLiterals2.ts, 214, 13)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 214, 24)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 214, 26)) +>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 214, 29)) +>options : Symbol(options, Decl(thisTypeInObjectLiterals2.ts, 214, 33)) +>VueOptions : Symbol(VueOptions, Decl(thisTypeInObjectLiterals2.ts, 206, 1)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 214, 24)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 214, 26)) +>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 214, 29)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 214, 24)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 214, 26)) +>P : Symbol(P, Decl(thisTypeInObjectLiterals2.ts, 214, 29)) let vue = new Vue({ ->vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 166, 3)) ->Vue : Symbol(Vue, Decl(thisTypeInObjectLiterals2.ts, 164, 13)) +>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 216, 3)) +>Vue : Symbol(Vue, Decl(thisTypeInObjectLiterals2.ts, 214, 13)) data: () => ({ x: 1, y: 2 }), ->data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 166, 19)) ->x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 167, 18)) ->y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 167, 24)) +>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 216, 19)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 217, 18)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 217, 24)) methods: { ->methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 167, 33)) +>methods : Symbol(methods, Decl(thisTypeInObjectLiterals2.ts, 217, 33)) f(x: string) { ->f : Symbol(f, Decl(thisTypeInObjectLiterals2.ts, 168, 14)) ->x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 169, 10)) +>f : Symbol(f, Decl(thisTypeInObjectLiterals2.ts, 218, 14)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 219, 10)) return this.x; ->this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 167, 18)) ->x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 167, 18)) +>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 217, 18)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 217, 18)) } }, computed: { ->computed : Symbol(computed, Decl(thisTypeInObjectLiterals2.ts, 172, 6)) +>computed : Symbol(computed, Decl(thisTypeInObjectLiterals2.ts, 222, 6)) test(): number { ->test : Symbol(test, Decl(thisTypeInObjectLiterals2.ts, 173, 15)) +>test : Symbol(test, Decl(thisTypeInObjectLiterals2.ts, 223, 15)) return this.x; ->this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 167, 18)) ->x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 167, 18)) +>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 217, 18)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 217, 18)) }, hello: { ->hello : Symbol(hello, Decl(thisTypeInObjectLiterals2.ts, 176, 10)) +>hello : Symbol(hello, Decl(thisTypeInObjectLiterals2.ts, 226, 10)) get() { ->get : Symbol(get, Decl(thisTypeInObjectLiterals2.ts, 177, 16)) +>get : Symbol(get, Decl(thisTypeInObjectLiterals2.ts, 227, 16)) return "hi"; }, set(value: string) { ->set : Symbol(set, Decl(thisTypeInObjectLiterals2.ts, 180, 14)) ->value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 181, 16)) +>set : Symbol(set, Decl(thisTypeInObjectLiterals2.ts, 230, 14)) +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 231, 16)) } } } }); vue; ->vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 166, 3)) +>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 216, 3)) vue.x; ->vue.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 167, 18)) ->vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 166, 3)) ->x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 167, 18)) +>vue.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 217, 18)) +>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 216, 3)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 217, 18)) vue.f("abc"); ->vue.f : Symbol(f, Decl(thisTypeInObjectLiterals2.ts, 168, 14)) ->vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 166, 3)) ->f : Symbol(f, Decl(thisTypeInObjectLiterals2.ts, 168, 14)) +>vue.f : Symbol(f, Decl(thisTypeInObjectLiterals2.ts, 218, 14)) +>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 216, 3)) +>f : Symbol(f, Decl(thisTypeInObjectLiterals2.ts, 218, 14)) vue.test; ->vue.test : Symbol(test, Decl(thisTypeInObjectLiterals2.ts, 173, 15)) ->vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 166, 3)) ->test : Symbol(test, Decl(thisTypeInObjectLiterals2.ts, 173, 15)) +>vue.test : Symbol(test, Decl(thisTypeInObjectLiterals2.ts, 223, 15)) +>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 216, 3)) +>test : Symbol(test, Decl(thisTypeInObjectLiterals2.ts, 223, 15)) vue.hello; ->vue.hello : Symbol(hello, Decl(thisTypeInObjectLiterals2.ts, 176, 10)) ->vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 166, 3)) ->hello : Symbol(hello, Decl(thisTypeInObjectLiterals2.ts, 176, 10)) +>vue.hello : Symbol(hello, Decl(thisTypeInObjectLiterals2.ts, 226, 10)) +>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 216, 3)) +>hello : Symbol(hello, Decl(thisTypeInObjectLiterals2.ts, 226, 10)) diff --git a/tests/baselines/reference/thisTypeInObjectLiterals2.types b/tests/baselines/reference/thisTypeInObjectLiterals2.types index cc41be6b8c6..2742ad2c408 100644 --- a/tests/baselines/reference/thisTypeInObjectLiterals2.types +++ b/tests/baselines/reference/thisTypeInObjectLiterals2.types @@ -141,6 +141,158 @@ let p1: Point = { } }; +let p2: Point | null = { +>p2 : Point | null +>Point : Point +>null : null +>{ x: 10, y: 20, moveBy(dx, dy, dz) { this.x += dx; this.y += dy; if (this.z && dz) { this.z += dz; } }} : { x: number; y: number; moveBy(dx: number, dy: number, dz: number | undefined): void; } + + x: 10, +>x : number +>10 : 10 + + y: 20, +>y : number +>20 : 20 + + moveBy(dx, dy, dz) { +>moveBy : (dx: number, dy: number, dz: number | undefined) => void +>dx : number +>dy : number +>dz : number | undefined + + this.x += dx; +>this.x += dx : number +>this.x : number +>this : Point +>x : number +>dx : number + + this.y += dy; +>this.y += dy : number +>this.y : number +>this : Point +>y : number +>dy : number + + if (this.z && dz) { +>this.z && dz : number | undefined +>this.z : number | undefined +>this : Point +>z : number | undefined +>dz : number | undefined + + this.z += dz; +>this.z += dz : number +>this.z : number +>this : Point +>z : number +>dz : number + } + } +}; + +let p3: Point | undefined = { +>p3 : Point | undefined +>Point : Point +>{ x: 10, y: 20, moveBy(dx, dy, dz) { this.x += dx; this.y += dy; if (this.z && dz) { this.z += dz; } }} : { x: number; y: number; moveBy(dx: number, dy: number, dz: number | undefined): void; } + + x: 10, +>x : number +>10 : 10 + + y: 20, +>y : number +>20 : 20 + + moveBy(dx, dy, dz) { +>moveBy : (dx: number, dy: number, dz: number | undefined) => void +>dx : number +>dy : number +>dz : number | undefined + + this.x += dx; +>this.x += dx : number +>this.x : number +>this : Point +>x : number +>dx : number + + this.y += dy; +>this.y += dy : number +>this.y : number +>this : Point +>y : number +>dy : number + + if (this.z && dz) { +>this.z && dz : number | undefined +>this.z : number | undefined +>this : Point +>z : number | undefined +>dz : number | undefined + + this.z += dz; +>this.z += dz : number +>this.z : number +>this : Point +>z : number +>dz : number + } + } +}; + +let p4: Point | null | undefined = { +>p4 : Point | null | undefined +>Point : Point +>null : null +>{ x: 10, y: 20, moveBy(dx, dy, dz) { this.x += dx; this.y += dy; if (this.z && dz) { this.z += dz; } }} : { x: number; y: number; moveBy(dx: number, dy: number, dz: number | undefined): void; } + + x: 10, +>x : number +>10 : 10 + + y: 20, +>y : number +>20 : 20 + + moveBy(dx, dy, dz) { +>moveBy : (dx: number, dy: number, dz: number | undefined) => void +>dx : number +>dy : number +>dz : number | undefined + + this.x += dx; +>this.x += dx : number +>this.x : number +>this : Point +>x : number +>dx : number + + this.y += dy; +>this.y += dy : number +>this.y : number +>this : Point +>y : number +>dy : number + + if (this.z && dz) { +>this.z && dz : number | undefined +>this.z : number | undefined +>this : Point +>z : number | undefined +>dz : number | undefined + + this.z += dz; +>this.z += dz : number +>this.z : number +>this : Point +>z : number +>dz : number + } + } +}; + declare function f1(p: Point): void; >f1 : (p: Point) => void >p : Point @@ -196,6 +348,62 @@ f1({ } }); +declare function f2(p: Point | null | undefined): void; +>f2 : (p: Point | null | undefined) => void +>p : Point | null | undefined +>Point : Point +>null : null + +f2({ +>f2({ x: 10, y: 20, moveBy(dx, dy, dz) { this.x += dx; this.y += dy; if (this.z && dz) { this.z += dz; } }}) : void +>f2 : (p: Point | null | undefined) => void +>{ x: 10, y: 20, moveBy(dx, dy, dz) { this.x += dx; this.y += dy; if (this.z && dz) { this.z += dz; } }} : { x: number; y: number; moveBy(dx: number, dy: number, dz: number | undefined): void; } + + x: 10, +>x : number +>10 : 10 + + y: 20, +>y : number +>20 : 20 + + moveBy(dx, dy, dz) { +>moveBy : (dx: number, dy: number, dz: number | undefined) => void +>dx : number +>dy : number +>dz : number | undefined + + this.x += dx; +>this.x += dx : number +>this.x : number +>this : Point +>x : number +>dx : number + + this.y += dy; +>this.y += dy : number +>this.y : number +>this : Point +>y : number +>dy : number + + if (this.z && dz) { +>this.z && dz : number | undefined +>this.z : number | undefined +>this : Point +>z : number | undefined +>dz : number | undefined + + this.z += dz; +>this.z += dz : number +>this.z : number +>this : Point +>z : number +>dz : number + } + } +}); + // In methods of an object literal with a contextual type that includes some // ThisType, 'this' is of type T. From 36513f21aba6b77ab1147320c82ac218c3c3df97 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 7 Mar 2017 09:14:51 -0800 Subject: [PATCH 58/65] Remove only undefined, not null | undefined, from declared type --- src/compiler/checker.ts | 2 +- .../defaultParameterAddsUndefinedWithStrictNullChecks.ts | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f17f079008b..8ba023ce05a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10929,7 +10929,7 @@ namespace ts { declaration.initializer && getFalsyFlags(declaredType) & TypeFlags.Undefined && !(getFalsyFlags(checkExpression(declaration.initializer)) & TypeFlags.Undefined); - return annotationIncludesUndefined ? getNonNullableType(declaredType) : declaredType; + return annotationIncludesUndefined ? getTypeWithFacts(declaredType, TypeFacts.NEUndefined) : declaredType; } function checkIdentifier(node: Identifier): Type { diff --git a/tests/cases/compiler/defaultParameterAddsUndefinedWithStrictNullChecks.ts b/tests/cases/compiler/defaultParameterAddsUndefinedWithStrictNullChecks.ts index 04a9e668b32..d2e167c83a3 100644 --- a/tests/cases/compiler/defaultParameterAddsUndefinedWithStrictNullChecks.ts +++ b/tests/cases/compiler/defaultParameterAddsUndefinedWithStrictNullChecks.ts @@ -27,6 +27,13 @@ function foo4(x: string | undefined = undefined, b: number) { x = undefined; } +type OptionalNullableString = string | null | undefined; +function allowsNull(val: OptionalNullableString = "") { + val = null; + val = 'string and null are both ok'; +} +allowsNull(null); // still allows passing null + // .d.ts should have `string | undefined` for foo1, foo2, foo3 and foo4 From 2325fda8a65b140e7b9b3c4b4e1e2f7dd7872629 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 7 Mar 2017 09:28:51 -0800 Subject: [PATCH 59/65] Move isFlowNarrowable call inside getFlowTypeOfReference --- src/compiler/checker.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8ba023ce05a..fbd3ac458f0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10242,8 +10242,11 @@ namespace ts { return reference.flowNode && (type.flags & TypeFlags.Narrowable || couldBeUninitialized); } - function getFlowTypeOfReference(reference: Node, declaredType: Type, initialType = declaredType, flowContainer?: Node) { + function getFlowTypeOfReference(reference: Node, declaredType: Type, initialType = declaredType, flowContainer?: Node, couldBeUninitialized?: boolean) { let key: string; + if (!isFlowNarrowable(reference, declaredType, couldBeUninitialized)) { + return declaredType; + } const visitedFlowStart = visitedFlowCount; const evolvedType = getTypeFromFlowType(getTypeAtFlowNode(reference.flowNode)); visitedFlowCount = visitedFlowStart; @@ -11053,7 +11056,7 @@ namespace ts { const initialType = assumeInitialized ? (isParameter ? removeOptionalityFromDeclaredType(type, getRootDeclaration(declaration) as VariableLikeDeclaration) : type) : type === autoType || type === autoArrayType ? undefinedType : includeFalsyTypes(type, TypeFlags.Undefined); - const flowType = isFlowNarrowable(node, type, !assumeInitialized) ? getFlowTypeOfReference(node, type, initialType, flowContainer) : type; + const flowType = getFlowTypeOfReference(node, type, initialType, flowContainer, !assumeInitialized); // A variable is considered uninitialized when it is possible to analyze the entire control flow graph // from declaration to use, and when the variable's declared type doesn't include undefined but the // control flow based type does include undefined. @@ -11319,7 +11322,7 @@ namespace ts { if (isClassLike(container.parent)) { const symbol = getSymbolOfNode(container.parent); const type = hasModifier(container, ModifierFlags.Static) ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol)).thisType; - return isFlowNarrowable(node, type) ? getFlowTypeOfReference(node, type) : type; + return getFlowTypeOfReference(node, type); } if (isInJavaScriptFile(node)) { @@ -13310,7 +13313,7 @@ namespace ts { !(prop.flags & SymbolFlags.Method && propType.flags & TypeFlags.Union)) { return propType; } - const flowType = isFlowNarrowable(node, propType) ? getFlowTypeOfReference(node, propType) : propType; + const flowType = getFlowTypeOfReference(node, propType); return assignmentKind ? getBaseTypeOfLiteralType(flowType) : flowType; } From c1f4c9c54360cad8ecffa8ab5524168ec7a55ab7 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 7 Mar 2017 09:29:29 -0800 Subject: [PATCH 60/65] Update baselines --- ...ameterAddsUndefinedWithStrictNullChecks.js | 15 +++++++ ...rAddsUndefinedWithStrictNullChecks.symbols | 39 +++++++++++++------ ...terAddsUndefinedWithStrictNullChecks.types | 25 ++++++++++++ 3 files changed, 68 insertions(+), 11 deletions(-) diff --git a/tests/baselines/reference/defaultParameterAddsUndefinedWithStrictNullChecks.js b/tests/baselines/reference/defaultParameterAddsUndefinedWithStrictNullChecks.js index 7f9cf553fe4..0477481c95c 100644 --- a/tests/baselines/reference/defaultParameterAddsUndefinedWithStrictNullChecks.js +++ b/tests/baselines/reference/defaultParameterAddsUndefinedWithStrictNullChecks.js @@ -26,6 +26,13 @@ function foo4(x: string | undefined = undefined, b: number) { x = undefined; } +type OptionalNullableString = string | null | undefined; +function allowsNull(val: OptionalNullableString = "") { + val = null; + val = 'string and null are both ok'; +} +allowsNull(null); // still allows passing null + // .d.ts should have `string | undefined` for foo1, foo2, foo3 and foo4 @@ -81,6 +88,12 @@ function foo4(x, b) { x; // should be string | undefined x = undefined; } +function allowsNull(val) { + if (val === void 0) { val = ""; } + val = null; + val = 'string and null are both ok'; +} +allowsNull(null); // still allows passing null // .d.ts should have `string | undefined` for foo1, foo2, foo3 and foo4 foo1(undefined, 1); foo2(undefined, 1); @@ -111,6 +124,8 @@ declare function foo1(x: string | undefined, b: number): void; declare function foo2(x: string | undefined, b: number): void; declare function foo3(x: string | undefined, b: number): void; declare function foo4(x: string | undefined, b: number): void; +declare type OptionalNullableString = string | null | undefined; +declare function allowsNull(val?: OptionalNullableString): void; declare function removeUndefinedButNotFalse(x?: boolean): false | undefined; declare const cond: boolean; declare function removeNothing(y?: boolean | undefined): boolean; diff --git a/tests/baselines/reference/defaultParameterAddsUndefinedWithStrictNullChecks.symbols b/tests/baselines/reference/defaultParameterAddsUndefinedWithStrictNullChecks.symbols index a484377f3f4..80abc32ee73 100644 --- a/tests/baselines/reference/defaultParameterAddsUndefinedWithStrictNullChecks.symbols +++ b/tests/baselines/reference/defaultParameterAddsUndefinedWithStrictNullChecks.symbols @@ -86,6 +86,23 @@ function foo4(x: string | undefined = undefined, b: number) { >undefined : Symbol(undefined) } +type OptionalNullableString = string | null | undefined; +>OptionalNullableString : Symbol(OptionalNullableString, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 25, 1)) + +function allowsNull(val: OptionalNullableString = "") { +>allowsNull : Symbol(allowsNull, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 27, 56)) +>val : Symbol(val, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 28, 20)) +>OptionalNullableString : Symbol(OptionalNullableString, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 25, 1)) + + val = null; +>val : Symbol(val, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 28, 20)) + + val = 'string and null are both ok'; +>val : Symbol(val, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 28, 20)) +} +allowsNull(null); // still allows passing null +>allowsNull : Symbol(allowsNull, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 27, 56)) + // .d.ts should have `string | undefined` for foo1, foo2, foo3 and foo4 @@ -107,35 +124,35 @@ foo4(undefined, 1); function removeUndefinedButNotFalse(x = true) { ->removeUndefinedButNotFalse : Symbol(removeUndefinedButNotFalse, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 33, 19)) ->x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 36, 36)) +>removeUndefinedButNotFalse : Symbol(removeUndefinedButNotFalse, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 40, 19)) +>x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 43, 36)) if (x === false) { ->x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 36, 36)) +>x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 43, 36)) return x; ->x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 36, 36)) +>x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 43, 36)) } } declare const cond: boolean; ->cond : Symbol(cond, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 42, 13)) +>cond : Symbol(cond, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 49, 13)) function removeNothing(y = cond ? true : undefined) { ->removeNothing : Symbol(removeNothing, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 42, 28)) ->y : Symbol(y, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 43, 23)) ->cond : Symbol(cond, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 42, 13)) +>removeNothing : Symbol(removeNothing, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 49, 28)) +>y : Symbol(y, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 50, 23)) +>cond : Symbol(cond, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 49, 13)) >undefined : Symbol(undefined) if (y !== undefined) { ->y : Symbol(y, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 43, 23)) +>y : Symbol(y, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 50, 23)) >undefined : Symbol(undefined) if (y === false) { ->y : Symbol(y, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 43, 23)) +>y : Symbol(y, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 50, 23)) return y; ->y : Symbol(y, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 43, 23)) +>y : Symbol(y, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 50, 23)) } } return true; diff --git a/tests/baselines/reference/defaultParameterAddsUndefinedWithStrictNullChecks.types b/tests/baselines/reference/defaultParameterAddsUndefinedWithStrictNullChecks.types index 54b9cdf2a9b..8b8aea6370f 100644 --- a/tests/baselines/reference/defaultParameterAddsUndefinedWithStrictNullChecks.types +++ b/tests/baselines/reference/defaultParameterAddsUndefinedWithStrictNullChecks.types @@ -116,6 +116,31 @@ function foo4(x: string | undefined = undefined, b: number) { >undefined : undefined } +type OptionalNullableString = string | null | undefined; +>OptionalNullableString : OptionalNullableString +>null : null + +function allowsNull(val: OptionalNullableString = "") { +>allowsNull : (val?: OptionalNullableString) => void +>val : OptionalNullableString +>OptionalNullableString : OptionalNullableString +>"" : "" + + val = null; +>val = null : null +>val : OptionalNullableString +>null : null + + val = 'string and null are both ok'; +>val = 'string and null are both ok' : "string and null are both ok" +>val : OptionalNullableString +>'string and null are both ok' : "string and null are both ok" +} +allowsNull(null); // still allows passing null +>allowsNull(null) : void +>allowsNull : (val?: OptionalNullableString) => void +>null : null + // .d.ts should have `string | undefined` for foo1, foo2, foo3 and foo4 From 0c53b539c8197c166e1357f64dc315fed2d1529a Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 7 Mar 2017 09:52:45 -0800 Subject: [PATCH 61/65] Fix more gulp.dests to use the relative path of the tsconfig --- Gulpfile.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gulpfile.ts b/Gulpfile.ts index 3d4bae39a32..ac6102353c0 100644 --- a/Gulpfile.ts +++ b/Gulpfile.ts @@ -416,7 +416,7 @@ gulp.task(servicesFile, false, ["lib", "generate-diagnostics"], () => { file.path = nodeDefinitionsFile; return content + "\r\nexport = ts;"; })) - .pipe(gulp.dest(".")), + .pipe(gulp.dest("src/services")), completedDts.pipe(clone()) .pipe(insert.transform((content, file) => { file.path = nodeStandaloneDefinitionsFile; @@ -477,12 +477,12 @@ gulp.task(tsserverLibraryFile, false, [servicesFile], (done) => { return merge2([ js.pipe(prependCopyright()) .pipe(sourcemaps.write(".")) - .pipe(gulp.dest(".")), + .pipe(gulp.dest("src/server")), dts.pipe(prependCopyright(/*outputCopyright*/true)) .pipe(insert.transform((content) => { return content + "\r\nexport = ts;\r\nexport as namespace ts;"; })) - .pipe(gulp.dest(".")) + .pipe(gulp.dest("src/server")) ]); }); From 24c8de21c471c2a866a5dff7ce006343bebae52e Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 7 Mar 2017 10:20:02 -0800 Subject: [PATCH 62/65] Inline isFlowNarrowable --- src/compiler/checker.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index fbd3ac458f0..932b2e9c331 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10238,13 +10238,9 @@ namespace ts { return false; } - function isFlowNarrowable(reference: Node, type: Type, couldBeUninitialized?: boolean) { - return reference.flowNode && (type.flags & TypeFlags.Narrowable || couldBeUninitialized); - } - function getFlowTypeOfReference(reference: Node, declaredType: Type, initialType = declaredType, flowContainer?: Node, couldBeUninitialized?: boolean) { let key: string; - if (!isFlowNarrowable(reference, declaredType, couldBeUninitialized)) { + if (!reference.flowNode || !couldBeUninitialized && !(declaredType.flags & TypeFlags.Narrowable)) { return declaredType; } const visitedFlowStart = visitedFlowCount; From 7f85c228e869c4e32c82b4bffda7c8eca3bb4f3b Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Tue, 7 Mar 2017 11:47:26 -0800 Subject: [PATCH 63/65] Fix tslint compilation in gulp --- Gulpfile.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gulpfile.ts b/Gulpfile.ts index ac6102353c0..e025ce6eaa8 100644 --- a/Gulpfile.ts +++ b/Gulpfile.ts @@ -960,7 +960,7 @@ gulp.task("update-sublime", "Updates the sublime plugin's tsserver", ["local", s }); gulp.task("build-rules", "Compiles tslint rules to js", () => { - const settings: tsc.Settings = getCompilerSettings({ module: "commonjs" }, /*useBuiltCompiler*/ false); + const settings: tsc.Settings = getCompilerSettings({ module: "commonjs", "lib": ["es6"] }, /*useBuiltCompiler*/ false); const dest = path.join(builtLocalDirectory, "tslint"); return gulp.src("scripts/tslint/**/*.ts") .pipe(newer({ From 3c751ecdad81f181e246477e06e841f27e8ef35b Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 7 Mar 2017 11:47:38 -0800 Subject: [PATCH 64/65] Update baseline --- .../reference/moduleExportAlias.types | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/baselines/reference/moduleExportAlias.types b/tests/baselines/reference/moduleExportAlias.types index 2fbc6322955..9fda7560e37 100644 --- a/tests/baselines/reference/moduleExportAlias.types +++ b/tests/baselines/reference/moduleExportAlias.types @@ -224,19 +224,19 @@ multipleDeclarationAlias5.func9 = function () { }; >function () { } : () => void var multipleDeclarationAlias6 = exports = module.exports = {}; ->multipleDeclarationAlias6 : {} ->exports = module.exports = {} : {} +>multipleDeclarationAlias6 : { [x: string]: any; } +>exports = module.exports = {} : { [x: string]: any; } >exports : any ->module.exports = {} : {} +>module.exports = {} : { [x: string]: any; } >module.exports : any >module : any >exports : any ->{} : {} +>{} : { [x: string]: any; } multipleDeclarationAlias6.func10 = function () { }; >multipleDeclarationAlias6.func10 = function () { } : () => void >multipleDeclarationAlias6.func10 : any ->multipleDeclarationAlias6 : {} +>multipleDeclarationAlias6 : { [x: string]: any; } >func10 : any >function () { } : () => void @@ -295,13 +295,13 @@ module.exports.func12 = function () { }; >function () { } : () => void exports = module.exports = {}; ->exports = module.exports = {} : {} +>exports = module.exports = {} : { [x: string]: any; } >exports : any ->module.exports = {} : {} +>module.exports = {} : { [x: string]: any; } >module.exports : any >module : any >exports : any ->{} : {} +>{} : { [x: string]: any; } exports.func13 = function () { }; >exports.func13 = function () { } : () => void @@ -320,13 +320,13 @@ module.exports.func14 = function () { }; >function () { } : () => void exports = module.exports = {}; ->exports = module.exports = {} : {} +>exports = module.exports = {} : { [x: string]: any; } >exports : any ->module.exports = {} : {} +>module.exports = {} : { [x: string]: any; } >module.exports : any >module : any >exports : any ->{} : {} +>{} : { [x: string]: any; } exports.func15 = function () { }; >exports.func15 = function () { } : () => void @@ -370,11 +370,11 @@ module.exports.func18 = function () { }; >function () { } : () => void module.exports = {}; ->module.exports = {} : {} +>module.exports = {} : { [x: string]: any; } >module.exports : any >module : any >exports : any ->{} : {} +>{} : { [x: string]: any; } exports.func19 = function () { }; >exports.func19 = function () { } : () => void From fab4ef0bdeae9d192c3efadeb7ef62fe9028d4cd Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Tue, 7 Mar 2017 13:26:41 -0800 Subject: [PATCH 65/65] cache semantic and declaration diagnostics in program (#14516) --- src/compiler/program.ts | 44 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index d9ddf486e0d..abb8b0b2f09 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -290,6 +290,11 @@ namespace ts { return resolutions; } + interface DiagnosticCache { + perFile?: FileMap; + allDiagnostics?: Diagnostic[]; + } + export function createProgram(rootNames: string[], options: CompilerOptions, host?: CompilerHost, oldProgram?: Program): Program { let program: Program; let files: SourceFile[] = []; @@ -298,6 +303,9 @@ namespace ts { let noDiagnosticsTypeChecker: TypeChecker; let classifiableNames: Map; + let cachedSemanticDiagnosticsForFile: DiagnosticCache = {}; + let cachedDeclarationDiagnosticsForFile: DiagnosticCache = {}; + let resolvedTypeReferenceDirectives = createMap(); let fileProcessingDiagnostics = createDiagnosticCollection(); @@ -899,6 +907,10 @@ namespace ts { } function getSemanticDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] { + return getAndCacheDiagnostics(sourceFile, cancellationToken, cachedSemanticDiagnosticsForFile, getSemanticDiagnosticsForFileNoCache); + } + + function getSemanticDiagnosticsForFileNoCache(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] { return runWithCancellationToken(() => { const typeChecker = getDiagnosticsProducingTypeChecker(); @@ -1094,7 +1106,11 @@ namespace ts { }); } - function getDeclarationDiagnosticsWorker(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] { + function getDeclarationDiagnosticsWorker(sourceFile: SourceFile | undefined, cancellationToken: CancellationToken): Diagnostic[] { + return getAndCacheDiagnostics(sourceFile, cancellationToken, cachedDeclarationDiagnosticsForFile, getDeclarationDiagnosticsForFileNoCache); + } + + function getDeclarationDiagnosticsForFileNoCache(sourceFile: SourceFile| undefined, cancellationToken: CancellationToken) { return runWithCancellationToken(() => { const resolver = getDiagnosticsProducingTypeChecker().getEmitResolver(sourceFile, cancellationToken); // Don't actually write any files since we're just getting diagnostics. @@ -1102,6 +1118,32 @@ namespace ts { }); } + function getAndCacheDiagnostics( + sourceFile: SourceFile | undefined, + cancellationToken: CancellationToken, + cache: DiagnosticCache, + getDiagnostics: (sourceFile: SourceFile, cancellationToken: CancellationToken) => Diagnostic[]) { + + const cachedResult = sourceFile + ? cache.perFile && cache.perFile.get(sourceFile.path) + : cache.allDiagnostics; + + if (cachedResult) { + return cachedResult; + } + const result = getDiagnostics(sourceFile, cancellationToken) || emptyArray; + if (sourceFile) { + if (!cache.perFile) { + cache.perFile = createFileMap(); + } + cache.perFile.set(sourceFile.path, result); + } + else { + cache.allDiagnostics = result; + } + return result; + } + function getDeclarationDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] { return isDeclarationFile(sourceFile) ? [] : getDeclarationDiagnosticsWorker(sourceFile, cancellationToken); }