diff --git a/Gulpfile.ts b/Gulpfile.ts index 3d4bae39a32..e025ce6eaa8 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")) ]); }); @@ -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({ diff --git a/Jakefile.js b/Jakefile.js index 489bf62bd97..b53af2e99a8 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -325,8 +325,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(" "); @@ -1095,7 +1101,8 @@ var tslintRules = [ "noInOperatorRule", "noIncrementDecrementRule", "objectLiteralSurroundingSpaceRule", - "noTypeAssertionWhitespaceRule" + "noTypeAssertionWhitespaceRule", + "noBomRule" ]; var tslintRulesFiles = tslintRules.map(function (p) { return path.join(tslintRuleDir, p + ".ts"); @@ -1107,7 +1114,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) { 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..418905e604c 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; } @@ -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(); // @@ -2289,7 +2289,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); @@ -2297,23 +2332,28 @@ 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 = 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; + } + break; } } @@ -2346,11 +2386,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/checker.ts b/src/compiler/checker.ts index c189475fd4d..aa7908f52c1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1,4 +1,4 @@ -/// +/// /// /* @internal */ @@ -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(); @@ -242,6 +244,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(); /** @@ -259,6 +262,7 @@ namespace ts { let globalNumberType: ObjectType; let globalBooleanType: ObjectType; let globalRegExpType: ObjectType; + let globalThisType: GenericType; let anyArrayType: Type; let autoArrayType: Type; let anyReadonlyArrayType: Type; @@ -434,6 +438,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); @@ -1564,7 +1574,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, @@ -3359,16 +3369,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) { @@ -3403,11 +3403,11 @@ 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); } - 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, @@ -3478,25 +3478,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 getWidenedTypeFromJSSpecialPropertyDeclarations(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 @@ -3509,7 +3525,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 +3623,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); } @@ -3653,7 +3669,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 = getWidenedTypeFromJSSpecialPropertyDeclarations(symbol); } else { type = getWidenedTypeForVariableLikeDeclaration(declaration, /*reportErrors*/ true); @@ -3726,7 +3742,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 +3757,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 +3840,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 +5601,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)); @@ -6083,6 +6099,11 @@ namespace ts { return deferredGlobalIterableIteratorType || (deferredGlobalIterableIteratorType = getGlobalType("IterableIterator", /*arity*/ 1, reportErrors)) || emptyGenericType; } + 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 @@ -6540,7 +6561,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); } @@ -9015,11 +9036,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 (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); + }; const stringIndexInfo = getIndexInfoOfType(type, IndexKind.String); const numberIndexInfo = getIndexInfoOfType(type, IndexKind.Number); return createAnonymousType(type.symbol, members, emptyArray, emptyArray, @@ -9126,7 +9155,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); @@ -9843,9 +9872,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); @@ -10065,8 +10093,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 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); + } + 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) { @@ -10204,14 +10255,11 @@ namespace ts { return false; } - function getFlowTypeOfReference(reference: Node, declaredType: Type, assumeInitialized: boolean, flowContainer: Node) { + function getFlowTypeOfReference(reference: Node, declaredType: Type, initialType = declaredType, flowContainer?: Node, couldBeUninitialized?: boolean) { let key: string; - if (!reference.flowNode || assumeInitialized && !(declaredType.flags & TypeFlags.Narrowable)) { + if (!reference.flowNode || !couldBeUninitialized && !(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; @@ -10632,8 +10680,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 +10787,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]); } @@ -10883,6 +10938,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 ? getTypeWithFacts(declaredType, TypeFacts.NEUndefined) : declaredType; + } + function checkIdentifier(node: Identifier): Type { const symbol = getResolvedSymbol(node); if (symbol === unknownSymbol) { @@ -11001,13 +11066,16 @@ 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 = 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. 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)); } @@ -11267,7 +11335,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 getFlowTypeOfReference(node, type); } if (isInJavaScriptFile(node)) { @@ -11277,7 +11345,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); } @@ -11502,8 +11570,29 @@ namespace ts { } } + function getContainingObjectLiteral(func: FunctionLikeDeclaration) { + 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; + } + + function getThisTypeArgument(type: Type): Type { + return getObjectFlags(type) & ObjectFlags.Reference && (type).target === globalThisType ? (type).typeArguments[0] : undefined; + } + + function getThisTypeFromContextualType(type: Type): Type { + return mapType(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) { + if (func.kind === SyntaxKind.ArrowFunction) { + return undefined; + } + if (isContextSensitiveFunctionOrObjectLiteralMethod(func)) { const contextualSignature = getContextualSignature(func); if (contextualSignature) { const thisParameter = contextualSignature.thisParameter; @@ -11512,6 +11601,40 @@ namespace ts { } } } + if (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); + } + // There was no contextual ThisType for the containing object literal, so the contextual type + // 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'. + 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; } @@ -11710,42 +11833,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 @@ -11904,6 +12000,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 { @@ -11994,31 +12100,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); } @@ -12027,7 +12114,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[] = []; @@ -12046,7 +12133,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) { @@ -12054,7 +12141,7 @@ namespace ts { } } else { - const type = checkExpressionForMutableLocation(e, contextualMapper); + const type = checkExpressionForMutableLocation(e, checkMode); elementTypes.push(type); } hasSpreadElement = hasSpreadElement || e.kind === SyntaxKind.SpreadElement; @@ -12169,7 +12256,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); @@ -12182,6 +12269,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; @@ -12196,14 +12284,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; @@ -12272,7 +12360,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)) { @@ -12319,8 +12407,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); @@ -12409,7 +12497,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; @@ -12418,7 +12506,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); @@ -12489,8 +12577,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) { @@ -12531,7 +12619,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 +13007,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); } } @@ -12983,9 +13071,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)); } @@ -13239,7 +13327,7 @@ namespace ts { !(prop.flags & SymbolFlags.Method && propType.flags & TypeFlags.Union)) { return propType; } - const flowType = getFlowTypeOfReference(node, propType, /*assumeInitialized*/ true, /*flowContainer*/ undefined); + const flowType = getFlowTypeOfReference(node, propType); return assignmentKind ? getBaseTypeOfLiteralType(flowType) : flowType; } @@ -14742,7 +14830,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; @@ -14846,9 +14934,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) { @@ -14862,21 +14950,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); } } } @@ -14896,7 +14984,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); @@ -14908,7 +14996,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, @@ -14976,7 +15064,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; @@ -14985,7 +15073,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 @@ -14997,12 +15085,12 @@ 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 : 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)); } @@ -15010,7 +15098,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 @@ -15054,13 +15142,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); @@ -15100,7 +15188,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); @@ -15108,7 +15196,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 @@ -15195,7 +15283,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 @@ -15205,7 +15293,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; } @@ -15213,7 +15301,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 @@ -15229,10 +15317,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; } @@ -15608,7 +15696,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); } @@ -15619,13 +15707,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) { @@ -15637,7 +15725,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 @@ -15661,7 +15749,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); } } } @@ -15669,7 +15757,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; @@ -15680,7 +15768,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; } @@ -15689,20 +15777,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; @@ -15790,17 +15878,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: @@ -16067,10 +16155,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); } @@ -16103,15 +16191,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 @@ -16119,7 +16212,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; @@ -16131,7 +16224,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); @@ -16154,12 +16247,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. @@ -16167,10 +16260,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); @@ -16181,19 +16274,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))); } } } @@ -16204,10 +16297,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 +16312,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 @@ -16227,14 +16322,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)) { @@ -16254,7 +16349,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); @@ -16276,9 +16371,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: @@ -16289,12 +16384,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: @@ -16315,23 +16410,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"); } @@ -16544,7 +16639,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); @@ -16925,13 +17020,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) { @@ -16942,11 +17032,6 @@ namespace ts { } } - function checkAccessorDeferred(node: AccessorDeclaration) { - checkSourceElement(node.body); - registerForUnusedIdentifiersCheck(node); - } - function checkMissingDeclaration(node: Node) { checkDecorators(node); } @@ -17856,7 +17941,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); } @@ -20613,7 +20698,7 @@ namespace ts { break; case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - checkAccessorDeferred(node); + checkAccessorDeclaration(node); break; case SyntaxKind.ClassExpression: checkClassExpressionDeferred(node); @@ -21970,9 +22055,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/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 6b4e9ff590e..4b3dc23d565 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -1,4 +1,4 @@ -/// +/// /// /// /// @@ -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: true, sourceMap: false, }; diff --git a/src/compiler/core.ts b/src/compiler/core.ts index c3c0ba77fe4..c380a39611d 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1,4 +1,4 @@ -/// +/// /// namespace ts { 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/emitter.ts b/src/compiler/emitter.ts index c286eb9df19..616be35270e 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1,4 +1,4 @@ -/// +/// /// /// /// @@ -826,8 +826,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/compiler/factory.ts b/src/compiler/factory.ts index 530b0a240c3..669c66c4337 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -1,4 +1,4 @@ -/// +/// /// namespace ts { diff --git a/src/compiler/program.ts b/src/compiler/program.ts index eb9f0f0e0a1..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); } @@ -1630,7 +1672,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/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 d51fdb12ac3..bb1732b57ea 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -1,4 +1,4 @@ -/// +/// /// /// /// diff --git a/src/compiler/transformers/destructuring.ts b/src/compiler/transformers/destructuring.ts index bb129cd1187..df372fd9a2c 100644 --- a/src/compiler/transformers/destructuring.ts +++ b/src/compiler/transformers/destructuring.ts @@ -43,7 +43,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/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 52c6db707c1..80a8c985c56 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -1,4 +1,4 @@ -/// +/// /// /// @@ -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()); } 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..885f8fad898 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -1,4 +1,4 @@ -/// +/// /// /// @@ -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/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 90b1d2cec81..1492a106d2b 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, @@ -519,6 +519,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 { @@ -963,7 +965,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 { @@ -3318,7 +3319,7 @@ allowSyntheticDefaultImports?: boolean; allowUnreachableCode?: boolean; allowUnusedLabels?: boolean; - alwaysStrict?: boolean; + alwaysStrict?: boolean; // Always combine with strict property baseUrl?: string; charset?: string; /* @internal */ configFilePath?: string; @@ -3354,9 +3355,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; @@ -3379,7 +3380,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; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index f37048a55d7..030b66813a5 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1,4 +1,4 @@ -/// +/// /* @internal */ namespace ts { @@ -1429,6 +1429,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 { @@ -3152,15 +3167,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) { diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index db504847e27..133c62e1926 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 9f949041866..cfa8c23eb43 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/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/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 1531b18bb9d..4d1b2a0b10c 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 2eae01c3520..12e62aaa7b9 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -1,4 +1,4 @@ -/// +/// /// /// diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index 262c2ba21fe..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. @@ -1366,6 +1366,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, 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 cbbe23650fb..397de9ead30 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 339f0288688..385816b1029 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -1,4 +1,4 @@ -/// +/// /// /// /// diff --git a/src/server/typingsInstaller/nodeTypingsInstaller.ts b/src/server/typingsInstaller/nodeTypingsInstaller.ts index 447a2c05429..0a69d701953 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 c48c5a2460c..bab5356e99c 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 1c157257051..3e07efbc3de 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 e2561e208f9..1773427fcea 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/completions.ts b/src/services/completions.ts index 6a4ee3485de..525f1a8416c 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)) { @@ -176,7 +178,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 @@ -278,489 +280,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); @@ -1487,20 +1006,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; } /** @@ -1778,59 +1295,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/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 b6a8f5b5d23..bc1e50391c8 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 a2a32f95fa4..d0cf8c0aec8 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/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/services.ts b/src/services/services.ts index beb52f70110..e370dccac32 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/tsconfig.json b/src/services/tsconfig.json index f5cd2cd475f..b1391bd7300 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", diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 0ffd5d27bc6..1b32b3bbad7 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/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/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/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/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/defaultParameterAddsUndefinedWithStrictNullChecks.js b/tests/baselines/reference/defaultParameterAddsUndefinedWithStrictNullChecks.js index 329c2fb19ce..0477481c95c 100644 --- a/tests/baselines/reference/defaultParameterAddsUndefinedWithStrictNullChecks.js +++ b/tests/baselines/reference/defaultParameterAddsUndefinedWithStrictNullChecks.js @@ -18,12 +18,21 @@ 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; } +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 @@ -72,11 +81,19 @@ 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; } +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); @@ -107,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 fb0fce7dc7f..80abc32ee73 100644 --- a/tests/baselines/reference/defaultParameterAddsUndefinedWithStrictNullChecks.symbols +++ b/tests/baselines/reference/defaultParameterAddsUndefinedWithStrictNullChecks.symbols @@ -66,18 +66,43 @@ 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) } +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 @@ -94,40 +119,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, 40, 19)) +>x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 43, 36)) if (x === false) { ->x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 34, 36)) +>x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 43, 36)) return x; ->x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 34, 36)) +>x : Symbol(x, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 43, 36)) } } declare const cond: boolean; ->cond : Symbol(cond, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 40, 13)) +>cond : Symbol(cond, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 49, 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, 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, 41, 23)) +>y : Symbol(y, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 50, 23)) >undefined : Symbol(undefined) if (y === false) { ->y : Symbol(y, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 41, 23)) +>y : Symbol(y, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 50, 23)) return y; ->y : Symbol(y, Decl(defaultParameterAddsUndefinedWithStrictNullChecks.ts, 41, 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 d95f9259891..8b8aea6370f 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,8 +109,38 @@ 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 } +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 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/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 { 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/inferringClassMembersFromAssignments.js b/tests/baselines/reference/inferringClassMembersFromAssignments.js new file mode 100644 index 00000000000..a7b9e4ff8f0 --- /dev/null +++ b/tests/baselines/reference/inferringClassMembersFromAssignments.js @@ -0,0 +1,163 @@ +//// [tests/cases/conformance/salsa/inferringClassMembersFromAssignments.ts] //// + +//// [a.js] + +class C { + constructor() { + if (Math.random()) { + this.inConstructor = 0; + } + else { + this.inConstructor = "string" + } + this.inMultiple = 0; + } + method() { + if (Math.random()) { + this.inMethod = 0; + } + else { + this.inMethod = "string" + } + this.inMultiple = "string"; + } + get() { + if (Math.random()) { + this.inGetter = 0; + } + else { + this.inGetter = "string" + } + this.inMultiple = false; + } + 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 stringOrNumberOrBoolean: string | number | boolean; + +var stringOrNumberOrBoolean = c.inMultiple; + + +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"; + } + this.inMultiple = 0; + } + C.prototype.method = function () { + if (Math.random()) { + this.inMethod = 0; + } + else { + this.inMethod = "string"; + } + this.inMultiple = "string"; + }; + C.prototype.get = function () { + if (Math.random()) { + this.inGetter = 0; + } + else { + this.inGetter = "string"; + } + this.inMultiple = false; + }; + 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 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 new file mode 100644 index 00000000000..9951339f8a8 --- /dev/null +++ b/tests/baselines/reference/inferringClassMembersFromAssignments.symbols @@ -0,0 +1,220 @@ +=== 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)) + } + 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, 10, 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, 12, 28), Decl(a.js, 15, 14)) +>this : Symbol(C, Decl(a.js, 0, 0)) +>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, 12, 28), Decl(a.js, 15, 14)) +>this : Symbol(C, Decl(a.js, 0, 0)) +>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, 19, 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, 21, 28), Decl(a.js, 24, 14)) +>this : Symbol(C, Decl(a.js, 0, 0)) +>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, 21, 28), Decl(a.js, 24, 14)) +>this : Symbol(C, Decl(a.js, 0, 0)) +>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, 28, 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, 30, 28), Decl(a.js, 33, 14)) +>this : Symbol(C, Decl(a.js, 0, 0)) +>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, 30, 28), Decl(a.js, 33, 14)) +>this : Symbol(C, Decl(a.js, 0, 0)) +>inSetter : Symbol(C.inSetter, Decl(a.js, 30, 28), Decl(a.js, 33, 14)) + } + } + static method() { +>method : Symbol(C.method, Decl(a.js, 36, 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, 38, 28), Decl(a.js, 41, 14)) +>this : Symbol(C, Decl(a.js, 0, 0)) +>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, 38, 28), Decl(a.js, 41, 14)) +>this : Symbol(C, Decl(a.js, 0, 0)) +>inStaticMethod : Symbol(C.inStaticMethod, Decl(a.js, 38, 28), Decl(a.js, 41, 14)) + } + } + static get() { +>get : Symbol(C.get, Decl(a.js, 44, 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, 46, 28), Decl(a.js, 49, 14)) +>this : Symbol(C, Decl(a.js, 0, 0)) +>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, 46, 28), Decl(a.js, 49, 14)) +>this : Symbol(C, Decl(a.js, 0, 0)) +>inStaticGetter : Symbol(C.inStaticGetter, Decl(a.js, 46, 28), Decl(a.js, 49, 14)) + } + } + static set() { +>set : Symbol(C.set, Decl(a.js, 52, 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, 54, 28), Decl(a.js, 57, 14)) +>this : Symbol(C, Decl(a.js, 0, 0)) +>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, 54, 28), Decl(a.js, 57, 14)) +>this : Symbol(C, Decl(a.js, 0, 0)) +>inStaticSetter : Symbol(C.inStaticSetter, Decl(a.js, 54, 28), Decl(a.js, 57, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 54, 28), Decl(a.js, 57, 14)) + diff --git a/tests/baselines/reference/inferringClassMembersFromAssignments.types b/tests/baselines/reference/inferringClassMembersFromAssignments.types new file mode 100644 index 00000000000..547cc62ba32 --- /dev/null +++ b/tests/baselines/reference/inferringClassMembersFromAssignments.types @@ -0,0 +1,262 @@ +=== 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" + } + this.inMultiple = 0; +>this.inMultiple = 0 : 0 +>this.inMultiple : string | number | boolean +>this : this +>inMultiple : string | number | boolean +>0 : 0 + } + 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" + } + this.inMultiple = "string"; +>this.inMultiple = "string" : "string" +>this.inMultiple : string | number | boolean +>this : this +>inMultiple : string | number | boolean +>"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" + } + this.inMultiple = false; +>this.inMultiple = false : false +>this.inMultiple : string | number | boolean +>this : this +>inMultiple : string | number | boolean +>false : false + } + 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 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 +>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/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/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/looseThisTypeInFunctions.errors.txt b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt index bf76c9c9641..cf4dcbd7dd5 100644 --- a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt +++ b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt @@ -1,12 +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(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 (4 errors) ==== +==== tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts (5 errors) ==== + interface I { n: number; explicitThis(this: this, m: number): number; @@ -36,6 +38,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/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/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..9fda7560e37 --- /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 : { [x: string]: any; } +>exports = module.exports = {} : { [x: string]: any; } +>exports : any +>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 : { [x: string]: any; } +>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 = {} : { [x: string]: any; } +>exports : any +>module.exports = {} : { [x: string]: any; } +>module.exports : any +>module : any +>exports : any +>{} : { [x: string]: 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 = {} : { [x: string]: any; } +>exports : any +>module.exports = {} : { [x: string]: any; } +>module.exports : any +>module : any +>exports : any +>{} : { [x: string]: 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 = {} : { [x: string]: any; } +>module.exports : any +>module : any +>exports : any +>{} : { [x: string]: 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/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 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 { } 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 edcc03b6bf6..8efadb7c077 100644 --- a/tests/baselines/reference/selfInLambdas.symbols +++ b/tests/baselines/reference/selfInLambdas.symbols @@ -1,44 +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, 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)) +>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)) } @@ -49,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 614ebc16e68..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 @@ -43,16 +44,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.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/thisBinding2.symbols b/tests/baselines/reference/thisBinding2.symbols index cdef9b60b3e..f8436f5248b 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(messenger, 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..52ff6789559 100644 --- a/tests/baselines/reference/thisInObjectLiterals.errors.txt +++ b/tests/baselines/reference/thisInObjectLiterals.errors.txt @@ -1,23 +1,28 @@ -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,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 (1 errors) ==== +==== 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: 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 }; } } //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; }; diff --git a/tests/baselines/reference/thisInObjectLiterals.js b/tests/baselines/reference/thisInObjectLiterals.js index 6c8380060a7..33a55cd5c71 100644 --- a/tests/baselines/reference/thisInObjectLiterals.js +++ b/tests/baselines/reference/thisInObjectLiterals.js @@ -1,11 +1,13 @@ //// [thisInObjectLiterals.ts] + 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/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/thisTypeInAccessorsNegative.errors.txt b/tests/baselines/reference/thisTypeInAccessorsNegative.errors.txt index 5396f1f4316..cd609673723 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; @@ -22,9 +21,6 @@ tests/cases/conformance/types/thisType/thisTypeInAccessorsNegative.ts(16,22): er } const contextual: Foo = { 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 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/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 f52438a19ab..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; @@ -33,15 +34,13 @@ 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 }, mine: 13, foo() { - this // this: any because of the string indexer + this // this: containing object literal type this.mine - this.willDestroy } }); @@ -70,15 +69,13 @@ 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; }, 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..d4b19caddb4 100644 --- a/tests/baselines/reference/thisTypeInFunctions2.symbols +++ b/tests/baselines/reference/thisTypeInFunctions2.symbols @@ -89,19 +89,24 @@ 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(IndexedWithoutThis, Decl(thisTypeInFunctions2.ts, 5, 1)) + this.mine - this.willDestroy +>this : Symbol(IndexedWithoutThis, Decl(thisTypeInFunctions2.ts, 5, 1)) + }, 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)) - this // this: any because of the string indexer this.mine - this.willDestroy +>this : Symbol(IndexedWithoutThis, Decl(thisTypeInFunctions2.ts, 5, 1)) } }); @@ -109,17 +114,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, 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, 47, 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)) +>bar : Symbol(SimpleInterface.bar, Decl(thisTypeInFunctions2.ts, 13, 19)) }, bar() { ->bar : Symbol(bar, Decl(thisTypeInFunctions2.ts, 49, 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 3cf6c1d2fae..a527429ccd9 100644 --- a/tests/baselines/reference/thisTypeInFunctions2.types +++ b/tests/baselines/reference/thisTypeInFunctions2.types @@ -92,26 +92,21 @@ 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 }, 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 }, 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 : IndexedWithoutThis this.mine >this.mine : any ->this : any +>this : IndexedWithoutThis >mine : any - this.willDestroy ->this.willDestroy : any ->this : any ->willDestroy : any - }, mine: 13, >mine : number @@ -120,39 +115,34 @@ extend2({ foo() { >foo : () => void - this // this: any because of the string indexer ->this : any + this // this: containing object literal type +>this : IndexedWithoutThis this.mine >this.mine : any ->this : any +>this : IndexedWithoutThis >mine : any - - this.willDestroy ->this.willDestroy : any ->this : any ->willDestroy : any } }); 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 : SimpleInterface +>bar : () => number }, bar() { 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 af4badf1c0f..374c790bd8f 100644 --- a/tests/baselines/reference/thisTypeInObjectLiterals.symbols +++ b/tests/baselines/reference/thisTypeInObjectLiterals.symbols @@ -1,80 +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, 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, 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, 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); ->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); ->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 240cfaa54f9..d4e6188b9cf 100644 --- a/tests/baselines/reference/thisTypeInObjectLiterals.types +++ b/tests/baselines/reference/thisTypeInObjectLiterals.types @@ -1,66 +1,67 @@ === 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 +75,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 +89,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 +114,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/thisTypeInObjectLiterals2.js b/tests/baselines/reference/thisTypeInObjectLiterals2.js new file mode 100644 index 00000000000..a9b666fda8f --- /dev/null +++ b/tests/baselines/reference/thisTypeInObjectLiterals2.js @@ -0,0 +1,493 @@ +//// [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; + z?: number; + moveBy(dx: number, dy: number, dz?: number): void; +} + +let p1: Point = { + x: 10, + y: 20, + moveBy(dx, dy, dz) { + this.x += dx; + this.y += dy; + if (this.z && dz) { + this.z += dz; + } + } +}; + +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({ + x: 10, + y: 20, + moveBy(dx, dy, dz) { + this.x += dx; + this.y += dy; + if (this.z && dz) { + this.z += dz; + } + } +}); + +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. + +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 + } + } +}); + +// 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 }; + +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. +"use strict"; +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, dz) { + this.x += dx; + this.y += dy; + if (this.z && dz) { + this.z += dz; + } + } +}; +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, + moveBy: function (dx, dy, dz) { + this.x += dx; + this.y += dy; + if (this.z && dz) { + this.z += dz; + } + } +}); +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: { + 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 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: { + 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; + z?: number; + 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; +}; +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 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; +}; +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..4c3e60c7536 --- /dev/null +++ b/tests/baselines/reference/thisTypeInObjectLiterals2.symbols @@ -0,0 +1,782 @@ +=== 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)) + + 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, 36, 3)) +>Point : Symbol(Point, Decl(thisTypeInObjectLiterals2.ts, 24, 2)) + + x: 10, +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 36, 17)) + + y: 20, +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 37, 10)) + + 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, 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, 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)) + } + } +}; + +let p2: Point | null = { +>p2 : Symbol(p2, Decl(thisTypeInObjectLiterals2.ts, 48, 3)) +>Point : Symbol(Point, Decl(thisTypeInObjectLiterals2.ts, 24, 2)) + + x: 10, +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 48, 24)) + + y: 20, +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 49, 10)) + + moveBy(dx, dy, dz) { +>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, 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, 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, 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, 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)) + } + } +}); + +// 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, 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, 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, 116, 13)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 115, 24)) +>ThisType : Symbol(ThisType, Decl(lib.d.ts, --, --)) +>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, 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, 122, 3)) +>makeObject : Symbol(makeObject, Decl(thisTypeInObjectLiterals2.ts, 118, 1)) + + data: { x: 0, y: 0 }, +>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, 123, 25)) + + moveBy(dx: number, dy: number) { +>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, 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, 123, 17)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 123, 17)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 125, 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, 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, 135, 23)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 135, 25)) + + data?: D; +>data : Symbol(data, Decl(thisTypeInObjectLiterals2.ts, 135, 50)) +>D : Symbol(D, Decl(thisTypeInObjectLiterals2.ts, 135, 23)) + + methods?: M; +>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, 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, 142, 3)) +>makeObject2 : Symbol(makeObject2, Decl(thisTypeInObjectLiterals2.ts, 138, 1)) + + data: { x: 0, y: 0 }, +>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, 143, 25)) + + moveBy(dx: number, dy: number) { +>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, 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, 143, 17)) +>y : Symbol(y, Decl(thisTypeInObjectLiterals2.ts, 143, 17)) +>dy : Symbol(dy, Decl(thisTypeInObjectLiterals2.ts, 145, 26)) + } + } +}); + +// Check pattern similar to Object.defineProperty and Object.defineProperties + +type PropDesc = { +>PropDesc : Symbol(PropDesc, Decl(thisTypeInObjectLiterals2.ts, 150, 3)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 154, 14)) + + value?: T; +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 154, 20)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 154, 14)) + + get?(): T; +>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, 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, 158, 1)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 160, 17)) + + [K in keyof T]: PropDesc; +>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, 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, 164, 28)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 164, 28)) +>Record : Symbol(Record, Decl(lib.d.ts, --, --)) +>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, 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, 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, 168, 3)) +>defineProp : Symbol(defineProp, Decl(thisTypeInObjectLiterals2.ts, 162, 1)) +>p1 : Symbol(p1, Decl(thisTypeInObjectLiterals2.ts, 36, 3)) +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 168, 33)) + +p10.foo = p10.foo + 1; +>p10.foo : Symbol(foo) +>p10 : Symbol(p10, Decl(thisTypeInObjectLiterals2.ts, 168, 3)) +>foo : Symbol(foo) +>p10.foo : Symbol(foo) +>p10 : Symbol(p10, Decl(thisTypeInObjectLiterals2.ts, 168, 3)) +>foo : Symbol(foo) + +let p11 = defineProp(p1, "bar", { +>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, 171, 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, 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, 175, 8)) + } +}); +p11.bar = p11.bar + 1; +>p11.bar : Symbol(bar) +>p11 : Symbol(p11, Decl(thisTypeInObjectLiterals2.ts, 171, 3)) +>bar : Symbol(bar) +>p11.bar : Symbol(bar) +>p11 : Symbol(p11, Decl(thisTypeInObjectLiterals2.ts, 171, 3)) +>bar : Symbol(bar) + +let p12 = defineProps(p1, { +>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, 181, 27)) + + value: 42 +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 182, 10)) + + }, + bar: { +>bar : Symbol(bar, Decl(thisTypeInObjectLiterals2.ts, 184, 6)) + + get(): number { +>get : Symbol(get, Decl(thisTypeInObjectLiterals2.ts, 185, 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, 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, 189, 12)) + } + } +}); +p12.foo = p12.foo + 1; +>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, 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, 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, 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, 201, 39)) +>T : Symbol(T, Decl(thisTypeInObjectLiterals2.ts, 203, 14)) + + get?(): T; +>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, 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, 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, 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, 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, 209, 25)) +>M : Symbol(M, Decl(thisTypeInObjectLiterals2.ts, 208, 18)) + + computed?: Accessors

; +>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, 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, 216, 3)) +>Vue : Symbol(Vue, Decl(thisTypeInObjectLiterals2.ts, 214, 13)) + + data: () => ({ x: 1, y: 2 }), +>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, 217, 33)) + + f(x: string) { +>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, 217, 18)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 217, 18)) + } + }, + computed: { +>computed : Symbol(computed, Decl(thisTypeInObjectLiterals2.ts, 222, 6)) + + test(): number { +>test : Symbol(test, Decl(thisTypeInObjectLiterals2.ts, 223, 15)) + + return this.x; +>this.x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 217, 18)) +>x : Symbol(x, Decl(thisTypeInObjectLiterals2.ts, 217, 18)) + + }, + hello: { +>hello : Symbol(hello, Decl(thisTypeInObjectLiterals2.ts, 226, 10)) + + get() { +>get : Symbol(get, Decl(thisTypeInObjectLiterals2.ts, 227, 16)) + + return "hi"; + }, + set(value: string) { +>set : Symbol(set, Decl(thisTypeInObjectLiterals2.ts, 230, 14)) +>value : Symbol(value, Decl(thisTypeInObjectLiterals2.ts, 231, 16)) + } + } + } +}); + +vue; +>vue : Symbol(vue, Decl(thisTypeInObjectLiterals2.ts, 216, 3)) + +vue.x; +>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, 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, 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, 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 new file mode 100644 index 00000000000..2742ad2c408 --- /dev/null +++ b/tests/baselines/reference/thisTypeInObjectLiterals2.types @@ -0,0 +1,897 @@ +=== 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 + + 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, 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 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 +>Point : Point + +f1({ +>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, 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 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. + +type ObjectDescriptor = { +>ObjectDescriptor : ObjectDescriptor +>D : D +>M : M + + data?: D; +>data : D | undefined +>D : D + + methods?: M & ThisType; // Type of 'this' in methods is D & M +>methods : (M & ThisType) | undefined +>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 | undefined +>D : D + + methods?: M; +>methods : M | undefined +>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 + } + } +}); + +// 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 }; +>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) | undefined +>T : T + + set?(value: T): void; +>set : ((value: T) => void) | undefined +>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) | undefined +>D : D +>D : D + + methods?: M; +>methods : M | undefined +>M : M + + computed?: Accessors

; +>computed : Accessors

| undefined +>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/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 diff --git a/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json b/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json index ea891967cb5..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", - "noImplicitAny": 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 abe135b4f16..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", - "noImplicitAny": 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 e28b66c8c2b..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", - "noImplicitAny": 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 5273b3cb7c8..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", - "noImplicitAny": 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 fa9cb6cad84..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", - "noImplicitAny": 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 ea891967cb5..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", - "noImplicitAny": 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 3ff8208d9d6..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", - "noImplicitAny": 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 b1740ac4c12..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", - "noImplicitAny": false, + "strict": true, "sourceMap": false, "types": [ "jquery", 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); + } + } +} 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 + } + } +} + 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/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 diff --git a/tests/cases/compiler/defaultParameterAddsUndefinedWithStrictNullChecks.ts b/tests/cases/compiler/defaultParameterAddsUndefinedWithStrictNullChecks.ts index 8abea19f6cd..d2e167c83a3 100644 --- a/tests/cases/compiler/defaultParameterAddsUndefinedWithStrictNullChecks.ts +++ b/tests/cases/compiler/defaultParameterAddsUndefinedWithStrictNullChecks.ts @@ -19,12 +19,21 @@ 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; } +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 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/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/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); + } + } +} 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..7ba7d5b2e91 100644 --- a/tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts +++ b/tests/cases/conformance/expressions/thisKeyword/thisInObjectLiterals.ts @@ -1,10 +1,14 @@ +// @noImplicitAny: true +// @noImplicitThis: true + 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/salsa/inferringClassMembersFromAssignments.ts b/tests/cases/conformance/salsa/inferringClassMembersFromAssignments.ts new file mode 100644 index 00000000000..d843e86b725 --- /dev/null +++ b/tests/cases/conformance/salsa/inferringClassMembersFromAssignments.ts @@ -0,0 +1,87 @@ +// @out: output.js +// @allowJs: true +// @strictNullChecks: true + +// @filename: a.js +class C { + constructor() { + if (Math.random()) { + this.inConstructor = 0; + } + else { + this.inConstructor = "string" + } + this.inMultiple = 0; + } + method() { + if (Math.random()) { + this.inMethod = 0; + } + else { + this.inMethod = "string" + } + this.inMultiple = "string"; + } + get() { + if (Math.random()) { + this.inGetter = 0; + } + else { + this.inGetter = "string" + } + this.inMultiple = false; + } + 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 stringOrNumberOrBoolean: string | number | boolean; + +var stringOrNumberOrBoolean = c.inMultiple; + + +var stringOrNumberOrUndefined = C.inStaticMethod; +var stringOrNumberOrUndefined = C.inStaticGetter; +var stringOrNumberOrUndefined = C.inStaticSetter; 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; + 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 () { }; + 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/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; } } diff --git a/tests/cases/conformance/types/thisType/thisTypeInFunctions2.ts b/tests/cases/conformance/types/thisType/thisTypeInFunctions2.ts index a574c7a07e9..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; @@ -32,15 +35,13 @@ 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 }, mine: 13, foo() { - this // this: any because of the string indexer + this // this: containing object literal type this.mine - this.willDestroy } }); 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() { diff --git a/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals2.ts b/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals2.ts new file mode 100644 index 00000000000..27861f81da6 --- /dev/null +++ b/tests/cases/conformance/types/thisType/thisTypeInObjectLiterals2.ts @@ -0,0 +1,245 @@ +// @declaration: true +// @strict: 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; + z?: number; + moveBy(dx: number, dy: number, dz?: number): void; +} + +let p1: Point = { + x: 10, + y: 20, + moveBy(dx, dy, dz) { + this.x += dx; + this.y += dy; + if (this.z && dz) { + this.z += dz; + } + } +}; + +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({ + x: 10, + y: 20, + moveBy(dx, dy, dz) { + this.x += dx; + this.y += dy; + if (this.z && dz) { + this.z += dz; + } + } +}); + +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. + +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 + } + } +}); + +// 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 }; + +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; 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; }"); 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(); diff --git a/tslint.json b/tslint.json index 3952d4fac29..5e72aedf065 100644 --- a/tslint.json +++ b/tslint.json @@ -1,5 +1,6 @@ { "rules": { + "no-bom": true, "class-name": true, "comment-format": [true, "check-space"