From 8e8a2397caffb09eb40905f95fe4ba92fd26d0e7 Mon Sep 17 00:00:00 2001 From: fullheightcoding Date: Thu, 25 Oct 2018 17:55:28 +1100 Subject: [PATCH 01/22] Fixed some typos. --- scripts/authors.ts | 14 +++++++------- scripts/bisect-test.ts | 2 +- scripts/createBenchmark.ts | 6 +++--- scripts/generateLocalizedDiagnosticMessages.ts | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/scripts/authors.ts b/scripts/authors.ts index b616ceb860..b52898244b 100644 --- a/scripts/authors.ts +++ b/scripts/authors.ts @@ -4,7 +4,7 @@ import child_process = require("child_process"); type Author = { displayNames: string[]; - preferedName?: string; + preferredName?: string; emails: string[]; }; @@ -20,7 +20,7 @@ const authorsPath = path.resolve("../AUTHORS.md"); function getKnownAuthors(): Author[] { const segmentRegExp = /\s?([^<]+)\s+<([^>]+)>/g; - const preferedNameRegeExp = /\s?#\s?([^#]+)$/; + const preferredNameRegeExp = /\s?#\s?([^#]+)$/; const knownAuthors: Author[] = []; if (!fs.existsSync(mailMapPath)) { @@ -37,13 +37,13 @@ function getKnownAuthors(): Author[] { author.displayNames.push(match[1]); author.emails.push(match[2]); } - if (match = preferedNameRegeExp.exec(line)) { - author.preferedName = match[1]; + if (match = preferredNameRegeExp.exec(line)) { + author.preferredName = match[1]; } if (!author.emails) continue; knownAuthors.push(author); - if (line.indexOf("#") > 0 && !author.preferedName) { - throw new Error("Could not match prefered name for: " + line); + if (line.indexOf("#") > 0 && !author.preferredName) { + throw new Error("Could not match preferred name for: " + line); } // console.log("===> line: " + line); // console.log(JSON.stringify(author, undefined, 2)); @@ -52,7 +52,7 @@ function getKnownAuthors(): Author[] { } function getAuthorName(author: Author) { - return author.preferedName || author.displayNames[0]; + return author.preferredName || author.displayNames[0]; } function getKnownAuthorMaps() { diff --git a/scripts/bisect-test.ts b/scripts/bisect-test.ts index 948b272470..cc0248f6d6 100644 --- a/scripts/bisect-test.ts +++ b/scripts/bisect-test.ts @@ -5,7 +5,7 @@ import cp = require('child_process'); import fs = require('fs'); -// Slice off 'node bisect-test.js' from the commandline args +// Slice off 'node bisect-test.js' from the command line args var args = process.argv.slice(2); function tsc(tscArgs: string, onExit: (exitCode: number) => void) { diff --git a/scripts/createBenchmark.ts b/scripts/createBenchmark.ts index 6148d80bf2..254c0d99af 100644 --- a/scripts/createBenchmark.ts +++ b/scripts/createBenchmark.ts @@ -30,7 +30,7 @@ var rawCompilerSources = ""; sourceFiles.forEach(f=> { rawCompilerSources += "\r\n" + fs.readFileSync(path.join(tsSourceDir, f)).toString(); }); -var compilerSoruces = `var compilerSources = ${JSON.stringify(rawCompilerSources) };`; +var compilerSources = `var compilerSources = ${JSON.stringify(rawCompilerSources) };`; // .js code for the compiler, what we are actually testing var rawCompilerJavaScript = fs.readFileSync(path.join(tsBuildDir, "tsc.js")).toString(); @@ -38,7 +38,7 @@ rawCompilerJavaScript = rawCompilerJavaScript.replace("ts.executeCommandLine(ts. // lib.d.ts sources var rawLibSources = fs.readFileSync(path.join(tsBuildDir, "lib.d.ts")).toString(); -var libSoruces = `var libSources = ${JSON.stringify(rawLibSources) };`; +var libSources = `var libSources = ${JSON.stringify(rawLibSources) };`; // write test output if (!fs.existsSync(testOutputDir)) { @@ -48,7 +48,7 @@ if (!fs.existsSync(testOutputDir)) { // 1. compiler ts sources, used to test fs.writeFileSync( path.join(testOutputDir, "compilerSources.js"), - `${ compilerSoruces } \r\n ${ libSoruces }`); + `${ compilerSources } \r\n ${ libSources }`); // 2. the compiler js sources + a call the compiler fs.writeFileSync( diff --git a/scripts/generateLocalizedDiagnosticMessages.ts b/scripts/generateLocalizedDiagnosticMessages.ts index 09d117d533..2374a9b4da 100644 --- a/scripts/generateLocalizedDiagnosticMessages.ts +++ b/scripts/generateLocalizedDiagnosticMessages.ts @@ -36,7 +36,7 @@ function main(): void { console.error("Unexpected XML file structure. Expected to find result.LCX.$.TgtCul."); process.exit(1); } - const outputDirectoryName = getPreferedLocaleName(result.LCX.$.TgtCul); + const outputDirectoryName = getPreferredLocaleName(result.LCX.$.TgtCul); if (!outputDirectoryName) { console.error(`Invalid output locale name for '${result.LCX.$.TgtCul}'.`); process.exit(1); @@ -64,7 +64,7 @@ function main(): void { * Most of the languages we support are neutral locales, so we want to use the language name. * There are three exceptions, zh-CN, zh-TW and pt-BR. */ - function getPreferedLocaleName(localeName: string) { + function getPreferredLocaleName(localeName: string) { switch (localeName) { case "zh-CN": case "zh-TW": From 01e71820fc62bcc31987f4a8912ed3fd023bd1dd Mon Sep 17 00:00:00 2001 From: AnyhowStep Date: Wed, 31 Oct 2018 17:00:24 -0400 Subject: [PATCH 02/22] Fixes Microsoft/TypeScript#6955 --- lib/lib.es5.d.ts | 4 ++-- src/lib/es5.d.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/lib.es5.d.ts b/lib/lib.es5.d.ts index d1a9d6f0d2..82d13bf3f1 100644 --- a/lib/lib.es5.d.ts +++ b/lib/lib.es5.d.ts @@ -1046,14 +1046,14 @@ interface JSON { * @param reviver A function that transforms the results. This function is called for each member of the object. * If a member contains nested objects, the nested objects are transformed before the parent object is. */ - parse(text: string, reviver?: (key: any, value: any) => any): any; + parse(text: string, reviver?: (this : any, key: string, value: any) => any): any; /** * Converts a JavaScript value to a JavaScript Object Notation (JSON) string. * @param value A JavaScript value, usually an object or array, to be converted. * @param replacer A function that transforms the results. * @param space Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read. */ - stringify(value: any, replacer?: (key: string, value: any) => any, space?: string | number): string; + stringify(value: any, replacer?: (this : any, key: string, value: any) => any, space?: string | number): string; /** * Converts a JavaScript value to a JavaScript Object Notation (JSON) string. * @param value A JavaScript value, usually an object or array, to be converted. diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index c8e99f0d1d..2da00df5a6 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -1026,14 +1026,14 @@ interface JSON { * @param reviver A function that transforms the results. This function is called for each member of the object. * If a member contains nested objects, the nested objects are transformed before the parent object is. */ - parse(text: string, reviver?: (key: any, value: any) => any): any; + parse(text: string, reviver?: (this : any, key: string, value: any) => any): any; /** * Converts a JavaScript value to a JavaScript Object Notation (JSON) string. * @param value A JavaScript value, usually an object or array, to be converted. * @param replacer A function that transforms the results. * @param space Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read. */ - stringify(value: any, replacer?: (key: string, value: any) => any, space?: string | number): string; + stringify(value: any, replacer?: (this : any, key: string, value: any) => any, space?: string | number): string; /** * Converts a JavaScript value to a JavaScript Object Notation (JSON) string. * @param value A JavaScript value, usually an object or array, to be converted. From e3ee7ae997f4cf4b1aa9e724739078d467f0a3fb Mon Sep 17 00:00:00 2001 From: AnyhowStep Date: Wed, 31 Oct 2018 17:29:03 -0400 Subject: [PATCH 03/22] Update baselines --- .../reference/controlFlowIfStatement.types | 4 ++-- .../controlFlowPropertyDeclarations.types | 4 ++-- .../baselines/reference/json.stringify.types | 22 +++++++++---------- tests/baselines/reference/parserharness.types | 4 ++-- ...ymousTypeNotReferencingTypeParameter.types | 4 ++-- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/tests/baselines/reference/controlFlowIfStatement.types b/tests/baselines/reference/controlFlowIfStatement.types index 03141e2618..35862e3265 100644 --- a/tests/baselines/reference/controlFlowIfStatement.types +++ b/tests/baselines/reference/controlFlowIfStatement.types @@ -101,9 +101,9 @@ function c(data: string | T): T { return JSON.parse(data); >JSON.parse(data) : any ->JSON.parse : (text: string, reviver?: (key: any, value: any) => any) => any +>JSON.parse : (text: string, reviver?: (this: any, key: string, value: any) => any) => any >JSON : JSON ->parse : (text: string, reviver?: (key: any, value: any) => any) => any +>parse : (text: string, reviver?: (this: any, key: string, value: any) => any) => any >data : string | (T & string) } else { diff --git a/tests/baselines/reference/controlFlowPropertyDeclarations.types b/tests/baselines/reference/controlFlowPropertyDeclarations.types index 0e698b7260..1cbe996961 100644 --- a/tests/baselines/reference/controlFlowPropertyDeclarations.types +++ b/tests/baselines/reference/controlFlowPropertyDeclarations.types @@ -316,9 +316,9 @@ export class HTMLtoJSX { >'{' + JSON.stringify(whitespace) : string >'{' : "{" >JSON.stringify(whitespace) : string ->JSON.stringify : { (value: any, replacer?: (key: string, value: any) => any, space?: string | number): string; (value: any, replacer?: (string | number)[], space?: string | number): string; } +>JSON.stringify : { (value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string; (value: any, replacer?: (string | number)[], space?: string | number): string; } >JSON : JSON ->stringify : { (value: any, replacer?: (key: string, value: any) => any, space?: string | number): string; (value: any, replacer?: (string | number)[], space?: string | number): string; } +>stringify : { (value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string; (value: any, replacer?: (string | number)[], space?: string | number): string; } >whitespace : string >'}' : "}" diff --git a/tests/baselines/reference/json.stringify.types b/tests/baselines/reference/json.stringify.types index a25eac5aaf..44f7636d46 100644 --- a/tests/baselines/reference/json.stringify.types +++ b/tests/baselines/reference/json.stringify.types @@ -5,27 +5,27 @@ var value = null; JSON.stringify(value, undefined, 2); >JSON.stringify(value, undefined, 2) : string ->JSON.stringify : { (value: any, replacer?: ((key: string, value: any) => any) | undefined, space?: string | number | undefined): string; (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string; } +>JSON.stringify : { (value: any, replacer?: ((this: any, key: string, value: any) => any) | undefined, space?: string | number | undefined): string; (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string; } >JSON : JSON ->stringify : { (value: any, replacer?: ((key: string, value: any) => any) | undefined, space?: string | number | undefined): string; (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string; } +>stringify : { (value: any, replacer?: ((this: any, key: string, value: any) => any) | undefined, space?: string | number | undefined): string; (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string; } >value : null >undefined : undefined >2 : 2 JSON.stringify(value, null, 2); >JSON.stringify(value, null, 2) : string ->JSON.stringify : { (value: any, replacer?: ((key: string, value: any) => any) | undefined, space?: string | number | undefined): string; (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string; } +>JSON.stringify : { (value: any, replacer?: ((this: any, key: string, value: any) => any) | undefined, space?: string | number | undefined): string; (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string; } >JSON : JSON ->stringify : { (value: any, replacer?: ((key: string, value: any) => any) | undefined, space?: string | number | undefined): string; (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string; } +>stringify : { (value: any, replacer?: ((this: any, key: string, value: any) => any) | undefined, space?: string | number | undefined): string; (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string; } >value : null >null : null >2 : 2 JSON.stringify(value, ["a", 1], 2); >JSON.stringify(value, ["a", 1], 2) : string ->JSON.stringify : { (value: any, replacer?: ((key: string, value: any) => any) | undefined, space?: string | number | undefined): string; (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string; } +>JSON.stringify : { (value: any, replacer?: ((this: any, key: string, value: any) => any) | undefined, space?: string | number | undefined): string; (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string; } >JSON : JSON ->stringify : { (value: any, replacer?: ((key: string, value: any) => any) | undefined, space?: string | number | undefined): string; (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string; } +>stringify : { (value: any, replacer?: ((this: any, key: string, value: any) => any) | undefined, space?: string | number | undefined): string; (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string; } >value : null >["a", 1] : (string | number)[] >"a" : "a" @@ -34,20 +34,20 @@ JSON.stringify(value, ["a", 1], 2); JSON.stringify(value, (k) => undefined, 2); >JSON.stringify(value, (k) => undefined, 2) : string ->JSON.stringify : { (value: any, replacer?: ((key: string, value: any) => any) | undefined, space?: string | number | undefined): string; (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string; } +>JSON.stringify : { (value: any, replacer?: ((this: any, key: string, value: any) => any) | undefined, space?: string | number | undefined): string; (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string; } >JSON : JSON ->stringify : { (value: any, replacer?: ((key: string, value: any) => any) | undefined, space?: string | number | undefined): string; (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string; } +>stringify : { (value: any, replacer?: ((this: any, key: string, value: any) => any) | undefined, space?: string | number | undefined): string; (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string; } >value : null ->(k) => undefined : (k: string) => undefined +>(k) => undefined : (this: any, k: string) => undefined >k : string >undefined : undefined >2 : 2 JSON.stringify(value, undefined, 2); >JSON.stringify(value, undefined, 2) : string ->JSON.stringify : { (value: any, replacer?: ((key: string, value: any) => any) | undefined, space?: string | number | undefined): string; (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string; } +>JSON.stringify : { (value: any, replacer?: ((this: any, key: string, value: any) => any) | undefined, space?: string | number | undefined): string; (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string; } >JSON : JSON ->stringify : { (value: any, replacer?: ((key: string, value: any) => any) | undefined, space?: string | number | undefined): string; (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string; } +>stringify : { (value: any, replacer?: ((this: any, key: string, value: any) => any) | undefined, space?: string | number | undefined): string; (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string; } >value : null >undefined : undefined >2 : 2 diff --git a/tests/baselines/reference/parserharness.types b/tests/baselines/reference/parserharness.types index 222ac9ab94..25bb34a6c5 100644 --- a/tests/baselines/reference/parserharness.types +++ b/tests/baselines/reference/parserharness.types @@ -7549,9 +7549,9 @@ module Harness { return JSON.stringify({ usePullLanguageService: usePull }); >JSON.stringify({ usePullLanguageService: usePull }) : string ->JSON.stringify : { (value: any, replacer?: (key: string, value: any) => any, space?: string | number): string; (value: any, replacer?: (string | number)[], space?: string | number): string; } +>JSON.stringify : { (value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string; (value: any, replacer?: (string | number)[], space?: string | number): string; } >JSON : JSON ->stringify : { (value: any, replacer?: (key: string, value: any) => any, space?: string | number): string; (value: any, replacer?: (string | number)[], space?: string | number): string; } +>stringify : { (value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string; (value: any, replacer?: (string | number)[], space?: string | number): string; } >{ usePullLanguageService: usePull } : { usePullLanguageService: boolean; } >usePullLanguageService : boolean >usePull : boolean diff --git a/tests/baselines/reference/staticAnonymousTypeNotReferencingTypeParameter.types b/tests/baselines/reference/staticAnonymousTypeNotReferencingTypeParameter.types index 382c14fb22..cd907c26ec 100644 --- a/tests/baselines/reference/staticAnonymousTypeNotReferencingTypeParameter.types +++ b/tests/baselines/reference/staticAnonymousTypeNotReferencingTypeParameter.types @@ -594,9 +594,9 @@ class ListWrapper { >ListWrapper : typeof ListWrapper >l : T[] >JSON.stringify(l) : string ->JSON.stringify : { (value: any, replacer?: (key: string, value: any) => any, space?: string | number): string; (value: any, replacer?: (string | number)[], space?: string | number): string; } +>JSON.stringify : { (value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string; (value: any, replacer?: (string | number)[], space?: string | number): string; } >JSON : JSON ->stringify : { (value: any, replacer?: (key: string, value: any) => any, space?: string | number): string; (value: any, replacer?: (string | number)[], space?: string | number): string; } +>stringify : { (value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string; (value: any, replacer?: (string | number)[], space?: string | number): string; } >l : T[] static maximum(dit: typeof ListWrapper, list: T[], predicate: (t: T) => number): T { From dd3ed0286885ff6e6dc0f8211f9281667387cf90 Mon Sep 17 00:00:00 2001 From: AnyhowStep Date: Tue, 13 Nov 2018 12:24:03 -0500 Subject: [PATCH 04/22] Removed stray whitespace --- lib/lib.es5.d.ts | 4 ++-- src/lib/es5.d.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/lib.es5.d.ts b/lib/lib.es5.d.ts index 82d13bf3f1..068ef13470 100644 --- a/lib/lib.es5.d.ts +++ b/lib/lib.es5.d.ts @@ -1046,14 +1046,14 @@ interface JSON { * @param reviver A function that transforms the results. This function is called for each member of the object. * If a member contains nested objects, the nested objects are transformed before the parent object is. */ - parse(text: string, reviver?: (this : any, key: string, value: any) => any): any; + parse(text: string, reviver?: (this: any, key: string, value: any) => any): any; /** * Converts a JavaScript value to a JavaScript Object Notation (JSON) string. * @param value A JavaScript value, usually an object or array, to be converted. * @param replacer A function that transforms the results. * @param space Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read. */ - stringify(value: any, replacer?: (this : any, key: string, value: any) => any, space?: string | number): string; + stringify(value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string; /** * Converts a JavaScript value to a JavaScript Object Notation (JSON) string. * @param value A JavaScript value, usually an object or array, to be converted. diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index 2da00df5a6..715b5f9fba 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -1026,14 +1026,14 @@ interface JSON { * @param reviver A function that transforms the results. This function is called for each member of the object. * If a member contains nested objects, the nested objects are transformed before the parent object is. */ - parse(text: string, reviver?: (this : any, key: string, value: any) => any): any; + parse(text: string, reviver?: (this: any, key: string, value: any) => any): any; /** * Converts a JavaScript value to a JavaScript Object Notation (JSON) string. * @param value A JavaScript value, usually an object or array, to be converted. * @param replacer A function that transforms the results. * @param space Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read. */ - stringify(value: any, replacer?: (this : any, key: string, value: any) => any, space?: string | number): string; + stringify(value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string; /** * Converts a JavaScript value to a JavaScript Object Notation (JSON) string. * @param value A JavaScript value, usually an object or array, to be converted. From a769c354848236544de3829c62770eaed1190007 Mon Sep 17 00:00:00 2001 From: Klaus Meinhardt Date: Sun, 23 Dec 2018 23:13:46 +0100 Subject: [PATCH 05/22] property is used before its initialization: check more nodes Fixes: #29125 --- src/compiler/checker.ts | 14 +++- .../useBeforeDeclaration_jsx.errors.txt | 38 ++++++++++ .../reference/useBeforeDeclaration_jsx.js | 28 ++++++++ .../useBeforeDeclaration_jsx.symbols | 55 +++++++++++++++ .../reference/useBeforeDeclaration_jsx.types | 69 +++++++++++++++++++ ...eDeclaration_propertyAssignment.errors.txt | 38 +++++++++- ...useBeforeDeclaration_propertyAssignment.js | 39 ++++++++--- ...foreDeclaration_propertyAssignment.symbols | 62 +++++++++++++++-- ...BeforeDeclaration_propertyAssignment.types | 69 ++++++++++++++++++- .../compiler/useBeforeDeclaration_jsx.tsx | 16 +++++ ...useBeforeDeclaration_propertyAssignment.ts | 16 ++++- 11 files changed, 422 insertions(+), 22 deletions(-) create mode 100644 tests/baselines/reference/useBeforeDeclaration_jsx.errors.txt create mode 100644 tests/baselines/reference/useBeforeDeclaration_jsx.js create mode 100644 tests/baselines/reference/useBeforeDeclaration_jsx.symbols create mode 100644 tests/baselines/reference/useBeforeDeclaration_jsx.types create mode 100644 tests/cases/compiler/useBeforeDeclaration_jsx.tsx diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 23c5568f2e..933ad041b9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -19094,7 +19094,19 @@ namespace ts { case SyntaxKind.PropertyDeclaration: return true; case SyntaxKind.PropertyAssignment: - // We might be in `a = { b: this.b }`, so keep looking. See `tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts`. + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.SpreadAssignment: + case SyntaxKind.ComputedPropertyName: + case SyntaxKind.TemplateSpan: + case SyntaxKind.JsxExpression: + case SyntaxKind.JsxAttribute: + case SyntaxKind.JsxAttributes: + case SyntaxKind.JsxSpreadAttribute: + case SyntaxKind.JsxOpeningElement: + case SyntaxKind.ExpressionWithTypeArguments: + case SyntaxKind.HeritageClause: return false; default: return isExpressionNode(node) ? false : "quit"; diff --git a/tests/baselines/reference/useBeforeDeclaration_jsx.errors.txt b/tests/baselines/reference/useBeforeDeclaration_jsx.errors.txt new file mode 100644 index 0000000000..ea15b24616 --- /dev/null +++ b/tests/baselines/reference/useBeforeDeclaration_jsx.errors.txt @@ -0,0 +1,38 @@ +tests/cases/compiler/useBeforeDeclaration_jsx.tsx(6,19): error TS2729: Property 'z' is used before its initialization. +tests/cases/compiler/useBeforeDeclaration_jsx.tsx(7,19): error TS2729: Property 'z' is used before its initialization. +tests/cases/compiler/useBeforeDeclaration_jsx.tsx(8,28): error TS2729: Property 'x' is used before its initialization. +tests/cases/compiler/useBeforeDeclaration_jsx.tsx(9,28): error TS2729: Property 'y' is used before its initialization. +tests/cases/compiler/useBeforeDeclaration_jsx.tsx(10,25): error TS2729: Property 'y' is used before its initialization. + + +==== tests/cases/compiler/useBeforeDeclaration_jsx.tsx (5 errors) ==== + namespace JSX { + export interface Element {} + } + + class C { + static a = ; + ~ +!!! error TS2729: Property 'z' is used before its initialization. +!!! related TS2728 tests/cases/compiler/useBeforeDeclaration_jsx.tsx:13:12: 'z' is declared here. + static b = ; + ~ +!!! error TS2729: Property 'z' is used before its initialization. +!!! related TS2728 tests/cases/compiler/useBeforeDeclaration_jsx.tsx:13:12: 'z' is declared here. + static c = ; + ~ +!!! error TS2729: Property 'x' is used before its initialization. +!!! related TS2728 tests/cases/compiler/useBeforeDeclaration_jsx.tsx:11:12: 'x' is declared here. + static d = ; + ~ +!!! error TS2729: Property 'y' is used before its initialization. +!!! related TS2728 tests/cases/compiler/useBeforeDeclaration_jsx.tsx:12:12: 'y' is declared here. + static e = {C.y}; + ~ +!!! error TS2729: Property 'y' is used before its initialization. +!!! related TS2728 tests/cases/compiler/useBeforeDeclaration_jsx.tsx:12:12: 'y' is declared here. + static x = {}; + static y = ''; + static z = () => ; + } + \ No newline at end of file diff --git a/tests/baselines/reference/useBeforeDeclaration_jsx.js b/tests/baselines/reference/useBeforeDeclaration_jsx.js new file mode 100644 index 0000000000..e95bf25464 --- /dev/null +++ b/tests/baselines/reference/useBeforeDeclaration_jsx.js @@ -0,0 +1,28 @@ +//// [useBeforeDeclaration_jsx.tsx] +namespace JSX { + export interface Element {} +} + +class C { + static a = ; + static b = ; + static c = ; + static d = ; + static e = {C.y}; + static x = {}; + static y = ''; + static z = () => ; +} + + +//// [useBeforeDeclaration_jsx.jsx] +class C { +} +C.a = ; +C.b = ; +C.c = ; +C.d = ; +C.e = {C.y}; +C.x = {}; +C.y = ''; +C.z = () => ; diff --git a/tests/baselines/reference/useBeforeDeclaration_jsx.symbols b/tests/baselines/reference/useBeforeDeclaration_jsx.symbols new file mode 100644 index 0000000000..434fe841fe --- /dev/null +++ b/tests/baselines/reference/useBeforeDeclaration_jsx.symbols @@ -0,0 +1,55 @@ +=== tests/cases/compiler/useBeforeDeclaration_jsx.tsx === +namespace JSX { +>JSX : Symbol(JSX, Decl(useBeforeDeclaration_jsx.tsx, 0, 0)) + + export interface Element {} +>Element : Symbol(Element, Decl(useBeforeDeclaration_jsx.tsx, 0, 15)) +} + +class C { +>C : Symbol(C, Decl(useBeforeDeclaration_jsx.tsx, 2, 1)) + + static a = ; +>a : Symbol(C.a, Decl(useBeforeDeclaration_jsx.tsx, 4, 9)) +>C.z : Symbol(C.z, Decl(useBeforeDeclaration_jsx.tsx, 11, 18)) +>C : Symbol(C, Decl(useBeforeDeclaration_jsx.tsx, 2, 1)) +>z : Symbol(C.z, Decl(useBeforeDeclaration_jsx.tsx, 11, 18)) +>C.z : Symbol(C.z, Decl(useBeforeDeclaration_jsx.tsx, 11, 18)) +>C : Symbol(C, Decl(useBeforeDeclaration_jsx.tsx, 2, 1)) +>z : Symbol(C.z, Decl(useBeforeDeclaration_jsx.tsx, 11, 18)) + + static b = ; +>b : Symbol(C.b, Decl(useBeforeDeclaration_jsx.tsx, 5, 27)) +>C.z : Symbol(C.z, Decl(useBeforeDeclaration_jsx.tsx, 11, 18)) +>C : Symbol(C, Decl(useBeforeDeclaration_jsx.tsx, 2, 1)) +>z : Symbol(C.z, Decl(useBeforeDeclaration_jsx.tsx, 11, 18)) + + static c = ; +>c : Symbol(C.c, Decl(useBeforeDeclaration_jsx.tsx, 6, 22)) +>C.x : Symbol(C.x, Decl(useBeforeDeclaration_jsx.tsx, 9, 34)) +>C : Symbol(C, Decl(useBeforeDeclaration_jsx.tsx, 2, 1)) +>x : Symbol(C.x, Decl(useBeforeDeclaration_jsx.tsx, 9, 34)) + + static d = ; +>d : Symbol(C.d, Decl(useBeforeDeclaration_jsx.tsx, 7, 38)) +>id : Symbol(id, Decl(useBeforeDeclaration_jsx.tsx, 8, 20)) +>C.y : Symbol(C.y, Decl(useBeforeDeclaration_jsx.tsx, 10, 18)) +>C : Symbol(C, Decl(useBeforeDeclaration_jsx.tsx, 2, 1)) +>y : Symbol(C.y, Decl(useBeforeDeclaration_jsx.tsx, 10, 18)) + + static e = {C.y}; +>e : Symbol(C.e, Decl(useBeforeDeclaration_jsx.tsx, 8, 38)) +>C.y : Symbol(C.y, Decl(useBeforeDeclaration_jsx.tsx, 10, 18)) +>C : Symbol(C, Decl(useBeforeDeclaration_jsx.tsx, 2, 1)) +>y : Symbol(C.y, Decl(useBeforeDeclaration_jsx.tsx, 10, 18)) + + static x = {}; +>x : Symbol(C.x, Decl(useBeforeDeclaration_jsx.tsx, 9, 34)) + + static y = ''; +>y : Symbol(C.y, Decl(useBeforeDeclaration_jsx.tsx, 10, 18)) + + static z = () => ; +>z : Symbol(C.z, Decl(useBeforeDeclaration_jsx.tsx, 11, 18)) +} + diff --git a/tests/baselines/reference/useBeforeDeclaration_jsx.types b/tests/baselines/reference/useBeforeDeclaration_jsx.types new file mode 100644 index 0000000000..18e0e34139 --- /dev/null +++ b/tests/baselines/reference/useBeforeDeclaration_jsx.types @@ -0,0 +1,69 @@ +=== tests/cases/compiler/useBeforeDeclaration_jsx.tsx === +namespace JSX { + export interface Element {} +} + +class C { +>C : C + + static a = ; +>a : JSX.Element +> : JSX.Element +>C.z : () => JSX.Element +>C : typeof C +>z : () => JSX.Element +>C.z : () => JSX.Element +>C : typeof C +>z : () => JSX.Element + + static b = ; +>b : JSX.Element +> : JSX.Element +>C.z : () => JSX.Element +>C : typeof C +>z : () => JSX.Element + + static c = ; +>c : JSX.Element +> : JSX.Element +>span : any +>C.x : {} +>C : typeof C +>x : {} +>span : any + + static d = ; +>d : JSX.Element +> : JSX.Element +>span : any +>id : string +>C.y : string +>C : typeof C +>y : string +>span : any + + static e = {C.y}; +>e : JSX.Element +>{C.y} : JSX.Element +>span : any +>C.y : string +>C : typeof C +>y : string +>span : any + + static x = {}; +>x : {} +>{} : {} + + static y = ''; +>y : string +>'' : "" + + static z = () => ; +>z : () => JSX.Element +>() => : () => JSX.Element +> : JSX.Element +>b : any +>b : any +} + diff --git a/tests/baselines/reference/useBeforeDeclaration_propertyAssignment.errors.txt b/tests/baselines/reference/useBeforeDeclaration_propertyAssignment.errors.txt index e58e7fa02e..b1b2174d1d 100644 --- a/tests/baselines/reference/useBeforeDeclaration_propertyAssignment.errors.txt +++ b/tests/baselines/reference/useBeforeDeclaration_propertyAssignment.errors.txt @@ -1,12 +1,44 @@ tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts(2,27): error TS2729: Property 'b' is used before its initialization. +tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts(2,38): error TS2729: Property 'c' is used before its initialization. +tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts(2,47): error TS2729: Property 'b' is used before its initialization. +tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts(2,59): error TS2729: Property 'c' is used before its initialization. +tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts(8,32): error TS2729: Property 'B' is used before its initialization. +tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts(13,12): error TS2729: Property 'D' is used before its initialization. -==== tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts (1 errors) ==== +==== tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts (6 errors) ==== export class C { - public a = { b: this.b }; + public a = { b: this.b, ...this.c, [this.b]: `${this.c}`}; ~ !!! error TS2729: Property 'b' is used before its initialization. !!! related TS2728 tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts:3:13: 'b' is declared here. + ~ +!!! error TS2729: Property 'c' is used before its initialization. +!!! related TS2728 tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts:4:12: 'c' is declared here. + ~ +!!! error TS2729: Property 'b' is used before its initialization. +!!! related TS2728 tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts:3:13: 'b' is declared here. + ~ +!!! error TS2729: Property 'c' is used before its initialization. +!!! related TS2728 tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts:4:12: 'c' is declared here. private b = 0; + public c = { c: this.b }; } - \ No newline at end of file + + class D { + static A = class extends D.B { + ~ +!!! error TS2729: Property 'B' is used before its initialization. +!!! related TS2728 tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts:11:12: 'B' is declared here. + [D.D]() {} // should be an error + } + static B = class {} + static C = { + [D.D]: 1, + ~ +!!! error TS2729: Property 'D' is used before its initialization. +!!! related TS2728 tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts:16:12: 'D' is declared here. + ...{get [D.D]() {return 0;}} // should be an error + }; + static D = ''; + } \ No newline at end of file diff --git a/tests/baselines/reference/useBeforeDeclaration_propertyAssignment.js b/tests/baselines/reference/useBeforeDeclaration_propertyAssignment.js index e34604e0a4..47968d429a 100644 --- a/tests/baselines/reference/useBeforeDeclaration_propertyAssignment.js +++ b/tests/baselines/reference/useBeforeDeclaration_propertyAssignment.js @@ -1,18 +1,37 @@ //// [useBeforeDeclaration_propertyAssignment.ts] export class C { - public a = { b: this.b }; + public a = { b: this.b, ...this.c, [this.b]: `${this.c}`}; private b = 0; + public c = { c: this.b }; } - + +class D { + static A = class extends D.B { + [D.D]() {} // should be an error + } + static B = class {} + static C = { + [D.D]: 1, + ...{get [D.D]() {return 0;}} // should be an error + }; + static D = ''; +} //// [useBeforeDeclaration_propertyAssignment.js] -"use strict"; -exports.__esModule = true; -var C = /** @class */ (function () { - function C() { - this.a = { b: this.b }; +export class C { + constructor() { + this.a = Object.assign({ b: this.b }, this.c, { [this.b]: `${this.c}` }); this.b = 0; + this.c = { c: this.b }; } - return C; -}()); -exports.C = C; +} +class D { +} +D.A = class extends D.B { + [D.D]() { } // should be an error +}; +D.B = class { +}; +D.C = Object.assign({ [D.D]: 1 }, { get [D.D]() { return 0; } } // should be an error +); +D.D = ''; diff --git a/tests/baselines/reference/useBeforeDeclaration_propertyAssignment.symbols b/tests/baselines/reference/useBeforeDeclaration_propertyAssignment.symbols index 5b067232ef..7c8acfc537 100644 --- a/tests/baselines/reference/useBeforeDeclaration_propertyAssignment.symbols +++ b/tests/baselines/reference/useBeforeDeclaration_propertyAssignment.symbols @@ -2,14 +2,68 @@ export class C { >C : Symbol(C, Decl(useBeforeDeclaration_propertyAssignment.ts, 0, 0)) - public a = { b: this.b }; + public a = { b: this.b, ...this.c, [this.b]: `${this.c}`}; >a : Symbol(C.a, Decl(useBeforeDeclaration_propertyAssignment.ts, 0, 16)) >b : Symbol(b, Decl(useBeforeDeclaration_propertyAssignment.ts, 1, 17)) ->this.b : Symbol(C.b, Decl(useBeforeDeclaration_propertyAssignment.ts, 1, 30)) +>this.b : Symbol(C.b, Decl(useBeforeDeclaration_propertyAssignment.ts, 1, 63)) >this : Symbol(C, Decl(useBeforeDeclaration_propertyAssignment.ts, 0, 0)) ->b : Symbol(C.b, Decl(useBeforeDeclaration_propertyAssignment.ts, 1, 30)) +>b : Symbol(C.b, Decl(useBeforeDeclaration_propertyAssignment.ts, 1, 63)) +>this.c : Symbol(C.c, Decl(useBeforeDeclaration_propertyAssignment.ts, 2, 18)) +>this : Symbol(C, Decl(useBeforeDeclaration_propertyAssignment.ts, 0, 0)) +>c : Symbol(C.c, Decl(useBeforeDeclaration_propertyAssignment.ts, 2, 18)) +>[this.b] : Symbol([this.b], Decl(useBeforeDeclaration_propertyAssignment.ts, 1, 39)) +>this.b : Symbol(C.b, Decl(useBeforeDeclaration_propertyAssignment.ts, 1, 63)) +>this : Symbol(C, Decl(useBeforeDeclaration_propertyAssignment.ts, 0, 0)) +>b : Symbol(C.b, Decl(useBeforeDeclaration_propertyAssignment.ts, 1, 63)) +>this.c : Symbol(C.c, Decl(useBeforeDeclaration_propertyAssignment.ts, 2, 18)) +>this : Symbol(C, Decl(useBeforeDeclaration_propertyAssignment.ts, 0, 0)) +>c : Symbol(C.c, Decl(useBeforeDeclaration_propertyAssignment.ts, 2, 18)) private b = 0; ->b : Symbol(C.b, Decl(useBeforeDeclaration_propertyAssignment.ts, 1, 30)) +>b : Symbol(C.b, Decl(useBeforeDeclaration_propertyAssignment.ts, 1, 63)) + + public c = { c: this.b }; +>c : Symbol(C.c, Decl(useBeforeDeclaration_propertyAssignment.ts, 2, 18)) +>c : Symbol(c, Decl(useBeforeDeclaration_propertyAssignment.ts, 3, 16)) +>this.b : Symbol(C.b, Decl(useBeforeDeclaration_propertyAssignment.ts, 1, 63)) +>this : Symbol(C, Decl(useBeforeDeclaration_propertyAssignment.ts, 0, 0)) +>b : Symbol(C.b, Decl(useBeforeDeclaration_propertyAssignment.ts, 1, 63)) } +class D { +>D : Symbol(D, Decl(useBeforeDeclaration_propertyAssignment.ts, 4, 1)) + + static A = class extends D.B { +>A : Symbol(D.A, Decl(useBeforeDeclaration_propertyAssignment.ts, 6, 9)) +>D.B : Symbol(D.B, Decl(useBeforeDeclaration_propertyAssignment.ts, 9, 5)) +>D : Symbol(D, Decl(useBeforeDeclaration_propertyAssignment.ts, 4, 1)) +>B : Symbol(D.B, Decl(useBeforeDeclaration_propertyAssignment.ts, 9, 5)) + + [D.D]() {} // should be an error +>[D.D] : Symbol((Anonymous class)[D.D], Decl(useBeforeDeclaration_propertyAssignment.ts, 7, 34)) +>D.D : Symbol(D.D, Decl(useBeforeDeclaration_propertyAssignment.ts, 14, 6)) +>D : Symbol(D, Decl(useBeforeDeclaration_propertyAssignment.ts, 4, 1)) +>D : Symbol(D.D, Decl(useBeforeDeclaration_propertyAssignment.ts, 14, 6)) + } + static B = class {} +>B : Symbol(D.B, Decl(useBeforeDeclaration_propertyAssignment.ts, 9, 5)) + + static C = { +>C : Symbol(D.C, Decl(useBeforeDeclaration_propertyAssignment.ts, 10, 23)) + + [D.D]: 1, +>[D.D] : Symbol([D.D], Decl(useBeforeDeclaration_propertyAssignment.ts, 11, 16)) +>D.D : Symbol(D.D, Decl(useBeforeDeclaration_propertyAssignment.ts, 14, 6)) +>D : Symbol(D, Decl(useBeforeDeclaration_propertyAssignment.ts, 4, 1)) +>D : Symbol(D.D, Decl(useBeforeDeclaration_propertyAssignment.ts, 14, 6)) + + ...{get [D.D]() {return 0;}} // should be an error +>[D.D] : Symbol([D.D], Decl(useBeforeDeclaration_propertyAssignment.ts, 13, 12)) +>D.D : Symbol(D.D, Decl(useBeforeDeclaration_propertyAssignment.ts, 14, 6)) +>D : Symbol(D, Decl(useBeforeDeclaration_propertyAssignment.ts, 4, 1)) +>D : Symbol(D.D, Decl(useBeforeDeclaration_propertyAssignment.ts, 14, 6)) + + }; + static D = ''; +>D : Symbol(D.D, Decl(useBeforeDeclaration_propertyAssignment.ts, 14, 6)) +} diff --git a/tests/baselines/reference/useBeforeDeclaration_propertyAssignment.types b/tests/baselines/reference/useBeforeDeclaration_propertyAssignment.types index cb30e36f28..e4136fde22 100644 --- a/tests/baselines/reference/useBeforeDeclaration_propertyAssignment.types +++ b/tests/baselines/reference/useBeforeDeclaration_propertyAssignment.types @@ -2,16 +2,79 @@ export class C { >C : C - public a = { b: this.b }; ->a : { b: number; } ->{ b: this.b } : { b: number; } + public a = { b: this.b, ...this.c, [this.b]: `${this.c}`}; +>a : { c: number; b: number; } +>{ b: this.b, ...this.c, [this.b]: `${this.c}`} : { c: number; b: number; } >b : number >this.b : number >this : this >b : number +>this.c : { c: number; } +>this : this +>c : { c: number; } +>[this.b] : string +>this.b : number +>this : this +>b : number +>`${this.c}` : string +>this.c : { c: number; } +>this : this +>c : { c: number; } private b = 0; >b : number >0 : 0 + + public c = { c: this.b }; +>c : { c: number; } +>{ c: this.b } : { c: number; } +>c : number +>this.b : number +>this : this +>b : number } +class D { +>D : D + + static A = class extends D.B { +>A : typeof (Anonymous class) +>class extends D.B { [D.D]() {} // should be an error } : typeof (Anonymous class) +>D.B : (Anonymous class) +>D : typeof D +>B : typeof (Anonymous class) + + [D.D]() {} // should be an error +>[D.D] : () => void +>D.D : string +>D : typeof D +>D : string + } + static B = class {} +>B : typeof (Anonymous class) +>class {} : typeof (Anonymous class) + + static C = { +>C : { [x: string]: number; } +>{ [D.D]: 1, ...{get [D.D]() {return 0;}} // should be an error } : { [x: string]: number; } + + [D.D]: 1, +>[D.D] : number +>D.D : string +>D : typeof D +>D : string +>1 : 1 + + ...{get [D.D]() {return 0;}} // should be an error +>{get [D.D]() {return 0;}} : { [x: string]: number; } +>[D.D] : number +>D.D : string +>D : typeof D +>D : string +>0 : 0 + + }; + static D = ''; +>D : string +>'' : "" +} diff --git a/tests/cases/compiler/useBeforeDeclaration_jsx.tsx b/tests/cases/compiler/useBeforeDeclaration_jsx.tsx new file mode 100644 index 0000000000..3995bf8a73 --- /dev/null +++ b/tests/cases/compiler/useBeforeDeclaration_jsx.tsx @@ -0,0 +1,16 @@ +// @jsx: preserve +// @target: ES6 +namespace JSX { + export interface Element {} +} + +class C { + static a = ; + static b = ; + static c = ; + static d = ; + static e = {C.y}; + static x = {}; + static y = ''; + static z = () => ; +} diff --git a/tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts b/tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts index bdd84473c5..6ce314bcc0 100644 --- a/tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts +++ b/tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts @@ -1,4 +1,18 @@ +// @target: ES6 export class C { - public a = { b: this.b }; + public a = { b: this.b, ...this.c, [this.b]: `${this.c}`}; private b = 0; + public c = { c: this.b }; } + +class D { + static A = class extends D.B { + [D.D]() {} // should be an error + } + static B = class {} + static C = { + [D.D]: 1, + ...{get [D.D]() {return 0;}} // should be an error + }; + static D = ''; +} \ No newline at end of file From c9c9f859f3f9118e707ff3cef6a2a02e2d599890 Mon Sep 17 00:00:00 2001 From: xiaofa Date: Thu, 17 Jan 2019 05:51:57 +0800 Subject: [PATCH 06/22] fix quick fix infer parameter types from usage in js file --- src/services/textChanges.ts | 4 +++- .../fourslash/codeFixInferFromUsageArrowJS.ts | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 tests/cases/fourslash/codeFixInferFromUsageArrowJS.ts diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index 4689e18508..7dab720584 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -340,7 +340,9 @@ namespace ts.textChanges { } public insertJsdocCommentBefore(sourceFile: SourceFile, node: HasJSDoc, tag: JSDoc): void { - const fnStart = node.getStart(sourceFile); + const fnStart = node.kind === SyntaxKind.ArrowFunction + ? node.parent.parent.getStart(sourceFile) + : node.getStart(sourceFile); if (node.jsDoc) { for (const jsdoc of node.jsDoc) { this.deleteRange(sourceFile, { diff --git a/tests/cases/fourslash/codeFixInferFromUsageArrowJS.ts b/tests/cases/fourslash/codeFixInferFromUsageArrowJS.ts new file mode 100644 index 0000000000..e867ae99c7 --- /dev/null +++ b/tests/cases/fourslash/codeFixInferFromUsageArrowJS.ts @@ -0,0 +1,18 @@ +/// +// @allowJs: true +// @checkJs: true +// @noEmit: true +// @noImplicitAny: true +// @Filename: test.js + +////const foo = x => x.y + 1; + +verify.codeFix({ + description: "Infer parameter types from usage", + index: 0, + newFileContent: +`/** + * @param {{ y: number; }} x + */ +const foo = x => x.y + 1;`, +}); \ No newline at end of file From 1b4bce236eeb2dc6ed0f3a5467b15f5bedeb2dfa Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 17 Jan 2019 14:37:31 -0800 Subject: [PATCH 07/22] Infer contextual types from return types through generic functions --- src/compiler/checker.ts | 46 +++++++++++++++++++++++++++-------------- src/compiler/types.ts | 1 + 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cb132ebf92..352a5c3159 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14591,18 +14591,18 @@ namespace ts { } function inferFromProperties(source: Type, target: Type) { - if (isTupleType(source)) { + if (isArrayType(source) || isTupleType(source)) { if (isTupleType(target)) { - const sourceLength = getLengthOfTupleType(source); + const sourceLength = isTupleType(source) ? getLengthOfTupleType(source) : 0; const targetLength = getLengthOfTupleType(target); - const sourceRestType = getRestTypeOfTupleType(source); + const sourceRestType = isTupleType(source) ? getRestTypeOfTupleType(source) : getElementTypeOfArrayType(source); const targetRestType = getRestTypeOfTupleType(target); const fixedLength = targetLength < sourceLength || sourceRestType ? targetLength : sourceLength; for (let i = 0; i < fixedLength; i++) { - inferFromTypes(i < sourceLength ? source.typeArguments![i] : sourceRestType!, target.typeArguments![i]); + inferFromTypes(i < sourceLength ? (source).typeArguments![i] : sourceRestType!, target.typeArguments![i]); } if (targetRestType) { - const types = fixedLength < sourceLength ? source.typeArguments!.slice(fixedLength, sourceLength) : []; + const types = fixedLength < sourceLength ? (source).typeArguments!.slice(fixedLength, sourceLength) : []; if (sourceRestType) { types.push(sourceRestType); } @@ -17694,14 +17694,28 @@ namespace ts { // Return the contextual type for a given expression node. During overload resolution, a contextual type may temporarily // be "pushed" onto a node using the contextualType property. function getApparentTypeOfContextualType(node: Expression): Type | undefined { - let contextualType = getContextualType(node); - contextualType = contextualType && mapType(contextualType, getApparentType); - if (contextualType && contextualType.flags & TypeFlags.Union) { - if (isObjectLiteralExpression(node)) { - return discriminateContextualTypeByObjectMembers(node, contextualType as UnionType); + const contextualType = instantiateContextualType(getContextualType(node), node); + if (contextualType) { + const apparentType = mapType(contextualType, getApparentType); + if (apparentType.flags & TypeFlags.Union) { + if (isObjectLiteralExpression(node)) { + return discriminateContextualTypeByObjectMembers(node, apparentType as UnionType); + } + else if (isJsxAttributes(node)) { + return discriminateContextualTypeByJSXAttributes(node, apparentType as UnionType); + } } - else if (isJsxAttributes(node)) { - return discriminateContextualTypeByJSXAttributes(node, contextualType as UnionType); + return apparentType; + } + } + + // If the given contextual type constains instantiable types and if a mapper representing + // return type inferences is available, instantiate those types using that mapper. + function instantiateContextualType(contextualType: Type | undefined, node: Expression): Type | undefined { + if (contextualType && maybeTypeOfKind(contextualType, TypeFlags.Instantiable)) { + const returnMapper = (getContextualMapper(node)).returnMapper; + if (returnMapper) { + return mapType(contextualType, t => t.flags & TypeFlags.Instantiable ? instantiateType(t, returnMapper) : t); } } return contextualType; @@ -19847,6 +19861,9 @@ namespace ts { const inferenceTargetType = getReturnTypeOfSignature(signature); // Inferences made from return types have lower priority than all other inferences. inferTypes(context.inferences, inferenceSourceType, inferenceTargetType, InferencePriority.ReturnType); + // Create a type mapper for instantiating generic contextual types using the inferences made + // from the return type. + context.returnMapper = cloneTypeMapper(context); } } @@ -23022,12 +23039,9 @@ namespace ts { } function checkExpressionForMutableLocation(node: Expression, checkMode: CheckMode | undefined, contextualType?: Type, forceTuple?: boolean): Type { - if (arguments.length === 2) { - contextualType = getContextualType(node); - } const type = checkExpression(node, checkMode, forceTuple); return isTypeAssertion(node) ? type : - getWidenedLiteralLikeTypeForContextualType(type, contextualType); + getWidenedLiteralLikeTypeForContextualType(type, instantiateContextualType(arguments.length === 2 ? getContextualType(node) : contextualType, node)); } function checkPropertyAssignment(node: PropertyAssignment, checkMode?: CheckMode): Type { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index c6c34c7434..a2e1fe7379 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4364,6 +4364,7 @@ namespace ts { inferences: InferenceInfo[]; // Inferences made for each type parameter flags: InferenceFlags; // Inference flags compareTypes: TypeComparer; // Type comparer function + returnMapper?: TypeMapper; // Type mapper for inferences from return types (if any) } /* @internal */ From da9feca0b00ad2fb59ca23a0cbe882066521f4bb Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 17 Jan 2019 14:38:04 -0800 Subject: [PATCH 08/22] Accept new baselines --- .../reference/errorMessagesIntersectionTypes02.errors.txt | 8 ++++---- .../reference/errorMessagesIntersectionTypes02.types | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/baselines/reference/errorMessagesIntersectionTypes02.errors.txt b/tests/baselines/reference/errorMessagesIntersectionTypes02.errors.txt index 6a9dd26706..1225d3662c 100644 --- a/tests/baselines/reference/errorMessagesIntersectionTypes02.errors.txt +++ b/tests/baselines/reference/errorMessagesIntersectionTypes02.errors.txt @@ -1,6 +1,6 @@ -tests/cases/compiler/errorMessagesIntersectionTypes02.ts(14,5): error TS2322: Type '{ fooProp: string; } & Bar' is not assignable to type 'FooBar'. +tests/cases/compiler/errorMessagesIntersectionTypes02.ts(14,5): error TS2322: Type '{ fooProp: "frizzlebizzle"; } & Bar' is not assignable to type 'FooBar'. Types of property 'fooProp' are incompatible. - Type 'string' is not assignable to type '"hello" | "world"'. + Type '"frizzlebizzle"' is not assignable to type '"hello" | "world"'. ==== tests/cases/compiler/errorMessagesIntersectionTypes02.ts (1 errors) ==== @@ -19,8 +19,8 @@ tests/cases/compiler/errorMessagesIntersectionTypes02.ts(14,5): error TS2322: Ty let fooBar: FooBar = mixBar({ ~~~~~~ -!!! error TS2322: Type '{ fooProp: string; } & Bar' is not assignable to type 'FooBar'. +!!! error TS2322: Type '{ fooProp: "frizzlebizzle"; } & Bar' is not assignable to type 'FooBar'. !!! error TS2322: Types of property 'fooProp' are incompatible. -!!! error TS2322: Type 'string' is not assignable to type '"hello" | "world"'. +!!! error TS2322: Type '"frizzlebizzle"' is not assignable to type '"hello" | "world"'. fooProp: "frizzlebizzle" }); \ No newline at end of file diff --git a/tests/baselines/reference/errorMessagesIntersectionTypes02.types b/tests/baselines/reference/errorMessagesIntersectionTypes02.types index ee21ee3ed9..f1aa28ca32 100644 --- a/tests/baselines/reference/errorMessagesIntersectionTypes02.types +++ b/tests/baselines/reference/errorMessagesIntersectionTypes02.types @@ -18,12 +18,12 @@ declare function mixBar(obj: T): T & Bar; let fooBar: FooBar = mixBar({ >fooBar : FooBar ->mixBar({ fooProp: "frizzlebizzle"}) : { fooProp: string; } & Bar +>mixBar({ fooProp: "frizzlebizzle"}) : { fooProp: "frizzlebizzle"; } & Bar >mixBar : (obj: T) => T & Bar ->{ fooProp: "frizzlebizzle"} : { fooProp: string; } +>{ fooProp: "frizzlebizzle"} : { fooProp: "frizzlebizzle"; } fooProp: "frizzlebizzle" ->fooProp : string +>fooProp : "frizzlebizzle" >"frizzlebizzle" : "frizzlebizzle" }); From bb1c91fac6945481e0a56cebce98b855482377e4 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 17 Jan 2019 17:04:29 -0800 Subject: [PATCH 09/22] Remove literal freshness when contextual type is a literal type --- src/compiler/checker.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 352a5c3159..f66667d2dd 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -22962,7 +22962,9 @@ namespace ts { context.contextualMapper = contextualMapper; const checkMode = contextualMapper === identityMapper ? CheckMode.SkipContextSensitive : contextualMapper ? CheckMode.Inferential : CheckMode.Contextual; - const result = checkExpression(node, checkMode); + const type = checkExpression(node, checkMode); + const result = maybeTypeOfKind(type, TypeFlags.Literal) && isLiteralOfContextualType(type, instantiateContextualType(contextualType, node)) ? + getRegularTypeOfLiteralType(type) : type; context.contextualType = saveContextualType; context.contextualMapper = saveContextualMapper; return result; From 4163d2dee4d78e26e831f9c369515fd1028d7cde Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 17 Jan 2019 17:16:52 -0800 Subject: [PATCH 10/22] Add tests --- .../inferFromGenericFunctionReturnTypes3.ts | 174 ++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts diff --git a/tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts b/tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts new file mode 100644 index 0000000000..e44e7c4a5e --- /dev/null +++ b/tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts @@ -0,0 +1,174 @@ +// @strict: true +// @target: es6 +// @declaration: true + +// Repros from #5487 + +function truePromise(): Promise { + return Promise.resolve(true); +} + +interface Wrap { + value: T; +} + +function wrap(value: T): Wrap { + return { value }; +} + +function wrappedFoo(): Wrap<'foo'> { + return wrap('foo'); +} + +function wrapBar(value: 'bar'): Wrap<'bar'> { + return { value }; +} + +function wrappedBar(): Wrap<'bar'> { + const value = 'bar'; + const inferred = wrapBar(value); + const literal = wrapBar('bar'); + const value2: string = 'bar'; + const literal2 = wrapBar(value2); // Error + return wrap(value); +} + +function wrappedBaz(): Wrap<'baz'> { + const value: 'baz' = 'baz'; + return wrap(value); +} + +// Repro from #11152 + +interface FolderContentItem { + type: 'folder' | 'file'; +} + +let a: FolderContentItem[] = []; +a = [1, 2, 3, 4, 5].map(v => ({ type: 'folder' })); + +// Repro from #11312 + +let arr: Array<[number, number]> = [[1, 2]] + +let mappedArr: Array<[number, number]> = arr.map(([x, y]) => { + return [x, y]; +}) + +// Repro from #13594 + +export namespace DiagnosticSeverity { + export const Error = 1; + export const Warning = 2; + export const Information = 3; + export const Hint = 4; +} + +export type DiagnosticSeverity = 1 | 2 | 3 | 4; + +export interface Diagnostic { + severity?: DiagnosticSeverity; + code?: number | string; + source?: string; + message: string; +} + +function bug(): Diagnostic[] { + let values: any[] = []; + return values.map((value) => { + return { + severity: DiagnosticSeverity.Error, + message: 'message' + } + }); +} + +// Repro from #22870 + +function objectToMap(obj: any) { + return new Map(Object.keys(obj).map(key => [key, obj[key]])); +}; + +// Repro from #24352 + +interface Person { + phoneNumbers: { + __typename: 'PhoneNumber'; + }[]; +} + +function createPerson(): Person { + return { + phoneNumbers: [1].map(() => ({ + __typename: 'PhoneNumber' + })) + }; +} + +// Repro from #26621 + +type Box = { value: T }; +declare function box(value: T): Box; + +type WinCondition = + | { type: 'win', player: string } + | { type: 'draw' }; + +let zz: Box = box({ type: 'draw' }); + +type WinType = 'win' | 'draw'; + +let yy: Box = box('draw'); + +// Repro from #27074 + +interface OK { + kind: "OK"; + value: T; +} +export function ok(value: T): OK { + return { + kind: "OK", + value: value + }; +} + +let result: OK<[string, number]> = ok(["hello", 12]); + +// Repro from #25889 + +interface I { + code: 'mapped', + name: string, +} + +const a3: I[] = ['a', 'b'].map(name => { + return { + code: 'mapped', + name, + } +}); + +// Repro from https://www.memsql.com/blog/porting-30k-lines-of-code-from-flow-to-typescript/ + +type Player = { + name: string; + age: number; + position: "STRIKER" | "GOALKEEPER", +}; + +type F = () => Promise>; + +const f1: F = () => { + return Promise.all([ + { + name: "David Gomes", + age: 23, + position: "GOALKEEPER", + }, { + name: "Cristiano Ronaldo", + age: 33, + position: "STRIKER", + } + ]); +}; From c809002bd3d07df7b6b60893a940c3079c4338fc Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 17 Jan 2019 17:17:03 -0800 Subject: [PATCH 11/22] Accept new baselines --- ...FromGenericFunctionReturnTypes3.errors.txt | 177 +++++++ .../inferFromGenericFunctionReturnTypes3.js | 285 +++++++++++ ...ferFromGenericFunctionReturnTypes3.symbols | 409 ++++++++++++++++ ...inferFromGenericFunctionReturnTypes3.types | 452 ++++++++++++++++++ 4 files changed, 1323 insertions(+) create mode 100644 tests/baselines/reference/inferFromGenericFunctionReturnTypes3.errors.txt create mode 100644 tests/baselines/reference/inferFromGenericFunctionReturnTypes3.js create mode 100644 tests/baselines/reference/inferFromGenericFunctionReturnTypes3.symbols create mode 100644 tests/baselines/reference/inferFromGenericFunctionReturnTypes3.types diff --git a/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.errors.txt b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.errors.txt new file mode 100644 index 0000000000..9a0d64c1a5 --- /dev/null +++ b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.errors.txt @@ -0,0 +1,177 @@ +tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts(28,30): error TS2345: Argument of type 'string' is not assignable to parameter of type '"bar"'. + + +==== tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts (1 errors) ==== + // Repros from #5487 + + function truePromise(): Promise { + return Promise.resolve(true); + } + + interface Wrap { + value: T; + } + + function wrap(value: T): Wrap { + return { value }; + } + + function wrappedFoo(): Wrap<'foo'> { + return wrap('foo'); + } + + function wrapBar(value: 'bar'): Wrap<'bar'> { + return { value }; + } + + function wrappedBar(): Wrap<'bar'> { + const value = 'bar'; + const inferred = wrapBar(value); + const literal = wrapBar('bar'); + const value2: string = 'bar'; + const literal2 = wrapBar(value2); // Error + ~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type '"bar"'. + return wrap(value); + } + + function wrappedBaz(): Wrap<'baz'> { + const value: 'baz' = 'baz'; + return wrap(value); + } + + // Repro from #11152 + + interface FolderContentItem { + type: 'folder' | 'file'; + } + + let a: FolderContentItem[] = []; + a = [1, 2, 3, 4, 5].map(v => ({ type: 'folder' })); + + // Repro from #11312 + + let arr: Array<[number, number]> = [[1, 2]] + + let mappedArr: Array<[number, number]> = arr.map(([x, y]) => { + return [x, y]; + }) + + // Repro from #13594 + + export namespace DiagnosticSeverity { + export const Error = 1; + export const Warning = 2; + export const Information = 3; + export const Hint = 4; + } + + export type DiagnosticSeverity = 1 | 2 | 3 | 4; + + export interface Diagnostic { + severity?: DiagnosticSeverity; + code?: number | string; + source?: string; + message: string; + } + + function bug(): Diagnostic[] { + let values: any[] = []; + return values.map((value) => { + return { + severity: DiagnosticSeverity.Error, + message: 'message' + } + }); + } + + // Repro from #22870 + + function objectToMap(obj: any) { + return new Map(Object.keys(obj).map(key => [key, obj[key]])); + }; + + // Repro from #24352 + + interface Person { + phoneNumbers: { + __typename: 'PhoneNumber'; + }[]; + } + + function createPerson(): Person { + return { + phoneNumbers: [1].map(() => ({ + __typename: 'PhoneNumber' + })) + }; + } + + // Repro from #26621 + + type Box = { value: T }; + declare function box(value: T): Box; + + type WinCondition = + | { type: 'win', player: string } + | { type: 'draw' }; + + let zz: Box = box({ type: 'draw' }); + + type WinType = 'win' | 'draw'; + + let yy: Box = box('draw'); + + // Repro from #27074 + + interface OK { + kind: "OK"; + value: T; + } + export function ok(value: T): OK { + return { + kind: "OK", + value: value + }; + } + + let result: OK<[string, number]> = ok(["hello", 12]); + + // Repro from #25889 + + interface I { + code: 'mapped', + name: string, + } + + const a3: I[] = ['a', 'b'].map(name => { + return { + code: 'mapped', + name, + } + }); + + // Repro from https://www.memsql.com/blog/porting-30k-lines-of-code-from-flow-to-typescript/ + + type Player = { + name: string; + age: number; + position: "STRIKER" | "GOALKEEPER", + }; + + type F = () => Promise>; + + const f1: F = () => { + return Promise.all([ + { + name: "David Gomes", + age: 23, + position: "GOALKEEPER", + }, { + name: "Cristiano Ronaldo", + age: 33, + position: "STRIKER", + } + ]); + }; + \ No newline at end of file diff --git a/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.js b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.js new file mode 100644 index 0000000000..ca1533bbab --- /dev/null +++ b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.js @@ -0,0 +1,285 @@ +//// [inferFromGenericFunctionReturnTypes3.ts] +// Repros from #5487 + +function truePromise(): Promise { + return Promise.resolve(true); +} + +interface Wrap { + value: T; +} + +function wrap(value: T): Wrap { + return { value }; +} + +function wrappedFoo(): Wrap<'foo'> { + return wrap('foo'); +} + +function wrapBar(value: 'bar'): Wrap<'bar'> { + return { value }; +} + +function wrappedBar(): Wrap<'bar'> { + const value = 'bar'; + const inferred = wrapBar(value); + const literal = wrapBar('bar'); + const value2: string = 'bar'; + const literal2 = wrapBar(value2); // Error + return wrap(value); +} + +function wrappedBaz(): Wrap<'baz'> { + const value: 'baz' = 'baz'; + return wrap(value); +} + +// Repro from #11152 + +interface FolderContentItem { + type: 'folder' | 'file'; +} + +let a: FolderContentItem[] = []; +a = [1, 2, 3, 4, 5].map(v => ({ type: 'folder' })); + +// Repro from #11312 + +let arr: Array<[number, number]> = [[1, 2]] + +let mappedArr: Array<[number, number]> = arr.map(([x, y]) => { + return [x, y]; +}) + +// Repro from #13594 + +export namespace DiagnosticSeverity { + export const Error = 1; + export const Warning = 2; + export const Information = 3; + export const Hint = 4; +} + +export type DiagnosticSeverity = 1 | 2 | 3 | 4; + +export interface Diagnostic { + severity?: DiagnosticSeverity; + code?: number | string; + source?: string; + message: string; +} + +function bug(): Diagnostic[] { + let values: any[] = []; + return values.map((value) => { + return { + severity: DiagnosticSeverity.Error, + message: 'message' + } + }); +} + +// Repro from #22870 + +function objectToMap(obj: any) { + return new Map(Object.keys(obj).map(key => [key, obj[key]])); +}; + +// Repro from #24352 + +interface Person { + phoneNumbers: { + __typename: 'PhoneNumber'; + }[]; +} + +function createPerson(): Person { + return { + phoneNumbers: [1].map(() => ({ + __typename: 'PhoneNumber' + })) + }; +} + +// Repro from #26621 + +type Box = { value: T }; +declare function box(value: T): Box; + +type WinCondition = + | { type: 'win', player: string } + | { type: 'draw' }; + +let zz: Box = box({ type: 'draw' }); + +type WinType = 'win' | 'draw'; + +let yy: Box = box('draw'); + +// Repro from #27074 + +interface OK { + kind: "OK"; + value: T; +} +export function ok(value: T): OK { + return { + kind: "OK", + value: value + }; +} + +let result: OK<[string, number]> = ok(["hello", 12]); + +// Repro from #25889 + +interface I { + code: 'mapped', + name: string, +} + +const a3: I[] = ['a', 'b'].map(name => { + return { + code: 'mapped', + name, + } +}); + +// Repro from https://www.memsql.com/blog/porting-30k-lines-of-code-from-flow-to-typescript/ + +type Player = { + name: string; + age: number; + position: "STRIKER" | "GOALKEEPER", +}; + +type F = () => Promise>; + +const f1: F = () => { + return Promise.all([ + { + name: "David Gomes", + age: 23, + position: "GOALKEEPER", + }, { + name: "Cristiano Ronaldo", + age: 33, + position: "STRIKER", + } + ]); +}; + + +//// [inferFromGenericFunctionReturnTypes3.js] +// Repros from #5487 +function truePromise() { + return Promise.resolve(true); +} +function wrap(value) { + return { value }; +} +function wrappedFoo() { + return wrap('foo'); +} +function wrapBar(value) { + return { value }; +} +function wrappedBar() { + const value = 'bar'; + const inferred = wrapBar(value); + const literal = wrapBar('bar'); + const value2 = 'bar'; + const literal2 = wrapBar(value2); // Error + return wrap(value); +} +function wrappedBaz() { + const value = 'baz'; + return wrap(value); +} +let a = []; +a = [1, 2, 3, 4, 5].map(v => ({ type: 'folder' })); +// Repro from #11312 +let arr = [[1, 2]]; +let mappedArr = arr.map(([x, y]) => { + return [x, y]; +}); +// Repro from #13594 +export var DiagnosticSeverity; +(function (DiagnosticSeverity) { + DiagnosticSeverity.Error = 1; + DiagnosticSeverity.Warning = 2; + DiagnosticSeverity.Information = 3; + DiagnosticSeverity.Hint = 4; +})(DiagnosticSeverity || (DiagnosticSeverity = {})); +function bug() { + let values = []; + return values.map((value) => { + return { + severity: DiagnosticSeverity.Error, + message: 'message' + }; + }); +} +// Repro from #22870 +function objectToMap(obj) { + return new Map(Object.keys(obj).map(key => [key, obj[key]])); +} +; +function createPerson() { + return { + phoneNumbers: [1].map(() => ({ + __typename: 'PhoneNumber' + })) + }; +} +let zz = box({ type: 'draw' }); +let yy = box('draw'); +export function ok(value) { + return { + kind: "OK", + value: value + }; +} +let result = ok(["hello", 12]); +const a3 = ['a', 'b'].map(name => { + return { + code: 'mapped', + name, + }; +}); +const f1 = () => { + return Promise.all([ + { + name: "David Gomes", + age: 23, + position: "GOALKEEPER", + }, { + name: "Cristiano Ronaldo", + age: 33, + position: "STRIKER", + } + ]); +}; + + +//// [inferFromGenericFunctionReturnTypes3.d.ts] +export declare namespace DiagnosticSeverity { + const Error = 1; + const Warning = 2; + const Information = 3; + const Hint = 4; +} +export declare type DiagnosticSeverity = 1 | 2 | 3 | 4; +export interface Diagnostic { + severity?: DiagnosticSeverity; + code?: number | string; + source?: string; + message: string; +} +interface OK { + kind: "OK"; + value: T; +} +export declare function ok(value: T): OK; +export {}; diff --git a/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.symbols b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.symbols new file mode 100644 index 0000000000..16beb0546d --- /dev/null +++ b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.symbols @@ -0,0 +1,409 @@ +=== tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts === +// Repros from #5487 + +function truePromise(): Promise { +>truePromise : Symbol(truePromise, Decl(inferFromGenericFunctionReturnTypes3.ts, 0, 0)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + return Promise.resolve(true); +>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +} + +interface Wrap { +>Wrap : Symbol(Wrap, Decl(inferFromGenericFunctionReturnTypes3.ts, 4, 1)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 6, 15)) + + value: T; +>value : Symbol(Wrap.value, Decl(inferFromGenericFunctionReturnTypes3.ts, 6, 19)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 6, 15)) +} + +function wrap(value: T): Wrap { +>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes3.ts, 8, 1)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 10, 14)) +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 10, 17)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 10, 14)) +>Wrap : Symbol(Wrap, Decl(inferFromGenericFunctionReturnTypes3.ts, 4, 1)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 10, 14)) + + return { value }; +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 11, 12)) +} + +function wrappedFoo(): Wrap<'foo'> { +>wrappedFoo : Symbol(wrappedFoo, Decl(inferFromGenericFunctionReturnTypes3.ts, 12, 1)) +>Wrap : Symbol(Wrap, Decl(inferFromGenericFunctionReturnTypes3.ts, 4, 1)) + + return wrap('foo'); +>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes3.ts, 8, 1)) +} + +function wrapBar(value: 'bar'): Wrap<'bar'> { +>wrapBar : Symbol(wrapBar, Decl(inferFromGenericFunctionReturnTypes3.ts, 16, 1)) +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 18, 17)) +>Wrap : Symbol(Wrap, Decl(inferFromGenericFunctionReturnTypes3.ts, 4, 1)) + + return { value }; +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 19, 12)) +} + +function wrappedBar(): Wrap<'bar'> { +>wrappedBar : Symbol(wrappedBar, Decl(inferFromGenericFunctionReturnTypes3.ts, 20, 1)) +>Wrap : Symbol(Wrap, Decl(inferFromGenericFunctionReturnTypes3.ts, 4, 1)) + + const value = 'bar'; +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 23, 9)) + + const inferred = wrapBar(value); +>inferred : Symbol(inferred, Decl(inferFromGenericFunctionReturnTypes3.ts, 24, 9)) +>wrapBar : Symbol(wrapBar, Decl(inferFromGenericFunctionReturnTypes3.ts, 16, 1)) +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 23, 9)) + + const literal = wrapBar('bar'); +>literal : Symbol(literal, Decl(inferFromGenericFunctionReturnTypes3.ts, 25, 9)) +>wrapBar : Symbol(wrapBar, Decl(inferFromGenericFunctionReturnTypes3.ts, 16, 1)) + + const value2: string = 'bar'; +>value2 : Symbol(value2, Decl(inferFromGenericFunctionReturnTypes3.ts, 26, 9)) + + const literal2 = wrapBar(value2); // Error +>literal2 : Symbol(literal2, Decl(inferFromGenericFunctionReturnTypes3.ts, 27, 9)) +>wrapBar : Symbol(wrapBar, Decl(inferFromGenericFunctionReturnTypes3.ts, 16, 1)) +>value2 : Symbol(value2, Decl(inferFromGenericFunctionReturnTypes3.ts, 26, 9)) + + return wrap(value); +>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes3.ts, 8, 1)) +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 23, 9)) +} + +function wrappedBaz(): Wrap<'baz'> { +>wrappedBaz : Symbol(wrappedBaz, Decl(inferFromGenericFunctionReturnTypes3.ts, 29, 1)) +>Wrap : Symbol(Wrap, Decl(inferFromGenericFunctionReturnTypes3.ts, 4, 1)) + + const value: 'baz' = 'baz'; +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 32, 9)) + + return wrap(value); +>wrap : Symbol(wrap, Decl(inferFromGenericFunctionReturnTypes3.ts, 8, 1)) +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 32, 9)) +} + +// Repro from #11152 + +interface FolderContentItem { +>FolderContentItem : Symbol(FolderContentItem, Decl(inferFromGenericFunctionReturnTypes3.ts, 34, 1)) + + type: 'folder' | 'file'; +>type : Symbol(FolderContentItem.type, Decl(inferFromGenericFunctionReturnTypes3.ts, 38, 29)) +} + +let a: FolderContentItem[] = []; +>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes3.ts, 42, 3)) +>FolderContentItem : Symbol(FolderContentItem, Decl(inferFromGenericFunctionReturnTypes3.ts, 34, 1)) + +a = [1, 2, 3, 4, 5].map(v => ({ type: 'folder' })); +>a : Symbol(a, Decl(inferFromGenericFunctionReturnTypes3.ts, 42, 3)) +>[1, 2, 3, 4, 5].map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) +>map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) +>v : Symbol(v, Decl(inferFromGenericFunctionReturnTypes3.ts, 43, 24)) +>type : Symbol(type, Decl(inferFromGenericFunctionReturnTypes3.ts, 43, 31)) + +// Repro from #11312 + +let arr: Array<[number, number]> = [[1, 2]] +>arr : Symbol(arr, Decl(inferFromGenericFunctionReturnTypes3.ts, 47, 3)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + +let mappedArr: Array<[number, number]> = arr.map(([x, y]) => { +>mappedArr : Symbol(mappedArr, Decl(inferFromGenericFunctionReturnTypes3.ts, 49, 3)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>arr.map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) +>arr : Symbol(arr, Decl(inferFromGenericFunctionReturnTypes3.ts, 47, 3)) +>map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes3.ts, 49, 51)) +>y : Symbol(y, Decl(inferFromGenericFunctionReturnTypes3.ts, 49, 53)) + + return [x, y]; +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes3.ts, 49, 51)) +>y : Symbol(y, Decl(inferFromGenericFunctionReturnTypes3.ts, 49, 53)) + +}) + +// Repro from #13594 + +export namespace DiagnosticSeverity { +>DiagnosticSeverity : Symbol(DiagnosticSeverity, Decl(inferFromGenericFunctionReturnTypes3.ts, 51, 2), Decl(inferFromGenericFunctionReturnTypes3.ts, 60, 1)) + + export const Error = 1; +>Error : Symbol(Error, Decl(inferFromGenericFunctionReturnTypes3.ts, 56, 13)) + + export const Warning = 2; +>Warning : Symbol(Warning, Decl(inferFromGenericFunctionReturnTypes3.ts, 57, 13)) + + export const Information = 3; +>Information : Symbol(Information, Decl(inferFromGenericFunctionReturnTypes3.ts, 58, 13)) + + export const Hint = 4; +>Hint : Symbol(Hint, Decl(inferFromGenericFunctionReturnTypes3.ts, 59, 13)) +} + +export type DiagnosticSeverity = 1 | 2 | 3 | 4; +>DiagnosticSeverity : Symbol(DiagnosticSeverity, Decl(inferFromGenericFunctionReturnTypes3.ts, 51, 2), Decl(inferFromGenericFunctionReturnTypes3.ts, 60, 1)) + +export interface Diagnostic { +>Diagnostic : Symbol(Diagnostic, Decl(inferFromGenericFunctionReturnTypes3.ts, 62, 47)) + + severity?: DiagnosticSeverity; +>severity : Symbol(Diagnostic.severity, Decl(inferFromGenericFunctionReturnTypes3.ts, 64, 29)) +>DiagnosticSeverity : Symbol(DiagnosticSeverity, Decl(inferFromGenericFunctionReturnTypes3.ts, 51, 2), Decl(inferFromGenericFunctionReturnTypes3.ts, 60, 1)) + + code?: number | string; +>code : Symbol(Diagnostic.code, Decl(inferFromGenericFunctionReturnTypes3.ts, 65, 31)) + + source?: string; +>source : Symbol(Diagnostic.source, Decl(inferFromGenericFunctionReturnTypes3.ts, 66, 24)) + + message: string; +>message : Symbol(Diagnostic.message, Decl(inferFromGenericFunctionReturnTypes3.ts, 67, 17)) +} + +function bug(): Diagnostic[] { +>bug : Symbol(bug, Decl(inferFromGenericFunctionReturnTypes3.ts, 69, 1)) +>Diagnostic : Symbol(Diagnostic, Decl(inferFromGenericFunctionReturnTypes3.ts, 62, 47)) + + let values: any[] = []; +>values : Symbol(values, Decl(inferFromGenericFunctionReturnTypes3.ts, 72, 4)) + + return values.map((value) => { +>values.map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) +>values : Symbol(values, Decl(inferFromGenericFunctionReturnTypes3.ts, 72, 4)) +>map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 73, 20)) + + return { + severity: DiagnosticSeverity.Error, +>severity : Symbol(severity, Decl(inferFromGenericFunctionReturnTypes3.ts, 74, 10)) +>DiagnosticSeverity.Error : Symbol(DiagnosticSeverity.Error, Decl(inferFromGenericFunctionReturnTypes3.ts, 56, 13)) +>DiagnosticSeverity : Symbol(DiagnosticSeverity, Decl(inferFromGenericFunctionReturnTypes3.ts, 51, 2), Decl(inferFromGenericFunctionReturnTypes3.ts, 60, 1)) +>Error : Symbol(DiagnosticSeverity.Error, Decl(inferFromGenericFunctionReturnTypes3.ts, 56, 13)) + + message: 'message' +>message : Symbol(message, Decl(inferFromGenericFunctionReturnTypes3.ts, 75, 38)) + } + }); +} + +// Repro from #22870 + +function objectToMap(obj: any) { +>objectToMap : Symbol(objectToMap, Decl(inferFromGenericFunctionReturnTypes3.ts, 79, 1)) +>obj : Symbol(obj, Decl(inferFromGenericFunctionReturnTypes3.ts, 83, 21)) + + return new Map(Object.keys(obj).map(key => [key, obj[key]])); +>Map : Symbol(Map, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Object.keys(obj).map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) +>Object.keys : Symbol(ObjectConstructor.keys, Decl(lib.es5.d.ts, --, --)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>keys : Symbol(ObjectConstructor.keys, Decl(lib.es5.d.ts, --, --)) +>obj : Symbol(obj, Decl(inferFromGenericFunctionReturnTypes3.ts, 83, 21)) +>map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) +>key : Symbol(key, Decl(inferFromGenericFunctionReturnTypes3.ts, 84, 37)) +>key : Symbol(key, Decl(inferFromGenericFunctionReturnTypes3.ts, 84, 37)) +>obj : Symbol(obj, Decl(inferFromGenericFunctionReturnTypes3.ts, 83, 21)) +>key : Symbol(key, Decl(inferFromGenericFunctionReturnTypes3.ts, 84, 37)) + +}; + +// Repro from #24352 + +interface Person { +>Person : Symbol(Person, Decl(inferFromGenericFunctionReturnTypes3.ts, 85, 2)) + + phoneNumbers: { +>phoneNumbers : Symbol(Person.phoneNumbers, Decl(inferFromGenericFunctionReturnTypes3.ts, 89, 18)) + + __typename: 'PhoneNumber'; +>__typename : Symbol(__typename, Decl(inferFromGenericFunctionReturnTypes3.ts, 90, 17)) + + }[]; +} + +function createPerson(): Person { +>createPerson : Symbol(createPerson, Decl(inferFromGenericFunctionReturnTypes3.ts, 93, 1)) +>Person : Symbol(Person, Decl(inferFromGenericFunctionReturnTypes3.ts, 85, 2)) + + return { + phoneNumbers: [1].map(() => ({ +>phoneNumbers : Symbol(phoneNumbers, Decl(inferFromGenericFunctionReturnTypes3.ts, 96, 10)) +>[1].map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) +>map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) + + __typename: 'PhoneNumber' +>__typename : Symbol(__typename, Decl(inferFromGenericFunctionReturnTypes3.ts, 97, 34)) + + })) + }; +} + +// Repro from #26621 + +type Box = { value: T }; +>Box : Symbol(Box, Decl(inferFromGenericFunctionReturnTypes3.ts, 101, 1)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 105, 9)) +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 105, 15)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 105, 9)) + +declare function box(value: T): Box; +>box : Symbol(box, Decl(inferFromGenericFunctionReturnTypes3.ts, 105, 27)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 106, 21)) +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 106, 24)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 106, 21)) +>Box : Symbol(Box, Decl(inferFromGenericFunctionReturnTypes3.ts, 101, 1)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 106, 21)) + +type WinCondition = +>WinCondition : Symbol(WinCondition, Decl(inferFromGenericFunctionReturnTypes3.ts, 106, 42)) + + | { type: 'win', player: string } +>type : Symbol(type, Decl(inferFromGenericFunctionReturnTypes3.ts, 109, 7)) +>player : Symbol(player, Decl(inferFromGenericFunctionReturnTypes3.ts, 109, 20)) + + | { type: 'draw' }; +>type : Symbol(type, Decl(inferFromGenericFunctionReturnTypes3.ts, 110, 7)) + +let zz: Box = box({ type: 'draw' }); +>zz : Symbol(zz, Decl(inferFromGenericFunctionReturnTypes3.ts, 112, 3)) +>Box : Symbol(Box, Decl(inferFromGenericFunctionReturnTypes3.ts, 101, 1)) +>WinCondition : Symbol(WinCondition, Decl(inferFromGenericFunctionReturnTypes3.ts, 106, 42)) +>box : Symbol(box, Decl(inferFromGenericFunctionReturnTypes3.ts, 105, 27)) +>type : Symbol(type, Decl(inferFromGenericFunctionReturnTypes3.ts, 112, 33)) + +type WinType = 'win' | 'draw'; +>WinType : Symbol(WinType, Decl(inferFromGenericFunctionReturnTypes3.ts, 112, 50)) + +let yy: Box = box('draw'); +>yy : Symbol(yy, Decl(inferFromGenericFunctionReturnTypes3.ts, 116, 3)) +>Box : Symbol(Box, Decl(inferFromGenericFunctionReturnTypes3.ts, 101, 1)) +>WinType : Symbol(WinType, Decl(inferFromGenericFunctionReturnTypes3.ts, 112, 50)) +>box : Symbol(box, Decl(inferFromGenericFunctionReturnTypes3.ts, 105, 27)) + +// Repro from #27074 + +interface OK { +>OK : Symbol(OK, Decl(inferFromGenericFunctionReturnTypes3.ts, 116, 35)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 120, 13)) + + kind: "OK"; +>kind : Symbol(OK.kind, Decl(inferFromGenericFunctionReturnTypes3.ts, 120, 17)) + + value: T; +>value : Symbol(OK.value, Decl(inferFromGenericFunctionReturnTypes3.ts, 121, 15)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 120, 13)) +} +export function ok(value: T): OK { +>ok : Symbol(ok, Decl(inferFromGenericFunctionReturnTypes3.ts, 123, 1)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 124, 19)) +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 124, 22)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 124, 19)) +>OK : Symbol(OK, Decl(inferFromGenericFunctionReturnTypes3.ts, 116, 35)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 124, 19)) + + return { + kind: "OK", +>kind : Symbol(kind, Decl(inferFromGenericFunctionReturnTypes3.ts, 125, 12)) + + value: value +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 126, 19)) +>value : Symbol(value, Decl(inferFromGenericFunctionReturnTypes3.ts, 124, 22)) + + }; +} + +let result: OK<[string, number]> = ok(["hello", 12]); +>result : Symbol(result, Decl(inferFromGenericFunctionReturnTypes3.ts, 131, 3)) +>OK : Symbol(OK, Decl(inferFromGenericFunctionReturnTypes3.ts, 116, 35)) +>ok : Symbol(ok, Decl(inferFromGenericFunctionReturnTypes3.ts, 123, 1)) + +// Repro from #25889 + +interface I { +>I : Symbol(I, Decl(inferFromGenericFunctionReturnTypes3.ts, 131, 53)) + + code: 'mapped', +>code : Symbol(I.code, Decl(inferFromGenericFunctionReturnTypes3.ts, 135, 13)) + + name: string, +>name : Symbol(I.name, Decl(inferFromGenericFunctionReturnTypes3.ts, 136, 19)) +} + +const a3: I[] = ['a', 'b'].map(name => { +>a3 : Symbol(a3, Decl(inferFromGenericFunctionReturnTypes3.ts, 140, 5)) +>I : Symbol(I, Decl(inferFromGenericFunctionReturnTypes3.ts, 131, 53)) +>['a', 'b'].map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) +>map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --)) +>name : Symbol(name, Decl(inferFromGenericFunctionReturnTypes3.ts, 140, 31)) + + return { + code: 'mapped', +>code : Symbol(code, Decl(inferFromGenericFunctionReturnTypes3.ts, 141, 12)) + + name, +>name : Symbol(name, Decl(inferFromGenericFunctionReturnTypes3.ts, 142, 23)) + } +}); + +// Repro from https://www.memsql.com/blog/porting-30k-lines-of-code-from-flow-to-typescript/ + +type Player = { +>Player : Symbol(Player, Decl(inferFromGenericFunctionReturnTypes3.ts, 145, 3)) + + name: string; +>name : Symbol(name, Decl(inferFromGenericFunctionReturnTypes3.ts, 149, 15)) + + age: number; +>age : Symbol(age, Decl(inferFromGenericFunctionReturnTypes3.ts, 150, 17)) + + position: "STRIKER" | "GOALKEEPER", +>position : Symbol(position, Decl(inferFromGenericFunctionReturnTypes3.ts, 151, 16)) + +}; + +type F = () => Promise>; +>F : Symbol(F, Decl(inferFromGenericFunctionReturnTypes3.ts, 153, 2)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Player : Symbol(Player, Decl(inferFromGenericFunctionReturnTypes3.ts, 145, 3)) + +const f1: F = () => { +>f1 : Symbol(f1, Decl(inferFromGenericFunctionReturnTypes3.ts, 157, 5)) +>F : Symbol(F, Decl(inferFromGenericFunctionReturnTypes3.ts, 153, 2)) + + return Promise.all([ +>Promise.all : Symbol(PromiseConstructor.all, Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --) ... and 6 more) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>all : Symbol(PromiseConstructor.all, Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --) ... and 6 more) + { + name: "David Gomes", +>name : Symbol(name, Decl(inferFromGenericFunctionReturnTypes3.ts, 159, 9)) + + age: 23, +>age : Symbol(age, Decl(inferFromGenericFunctionReturnTypes3.ts, 160, 32)) + + position: "GOALKEEPER", +>position : Symbol(position, Decl(inferFromGenericFunctionReturnTypes3.ts, 161, 20)) + + }, { + name: "Cristiano Ronaldo", +>name : Symbol(name, Decl(inferFromGenericFunctionReturnTypes3.ts, 163, 12)) + + age: 33, +>age : Symbol(age, Decl(inferFromGenericFunctionReturnTypes3.ts, 164, 38)) + + position: "STRIKER", +>position : Symbol(position, Decl(inferFromGenericFunctionReturnTypes3.ts, 165, 20)) + } + ]); +}; + diff --git a/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.types b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.types new file mode 100644 index 0000000000..e983cc6481 --- /dev/null +++ b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.types @@ -0,0 +1,452 @@ +=== tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts === +// Repros from #5487 + +function truePromise(): Promise { +>truePromise : () => Promise +>true : true + + return Promise.resolve(true); +>Promise.resolve(true) : Promise +>Promise.resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>Promise : PromiseConstructor +>resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>true : true +} + +interface Wrap { + value: T; +>value : T +} + +function wrap(value: T): Wrap { +>wrap : (value: T) => Wrap +>value : T + + return { value }; +>{ value } : { value: T; } +>value : T +} + +function wrappedFoo(): Wrap<'foo'> { +>wrappedFoo : () => Wrap<"foo"> + + return wrap('foo'); +>wrap('foo') : Wrap<"foo"> +>wrap : (value: T) => Wrap +>'foo' : "foo" +} + +function wrapBar(value: 'bar'): Wrap<'bar'> { +>wrapBar : (value: "bar") => Wrap<"bar"> +>value : "bar" + + return { value }; +>{ value } : { value: "bar"; } +>value : "bar" +} + +function wrappedBar(): Wrap<'bar'> { +>wrappedBar : () => Wrap<"bar"> + + const value = 'bar'; +>value : "bar" +>'bar' : "bar" + + const inferred = wrapBar(value); +>inferred : Wrap<"bar"> +>wrapBar(value) : Wrap<"bar"> +>wrapBar : (value: "bar") => Wrap<"bar"> +>value : "bar" + + const literal = wrapBar('bar'); +>literal : Wrap<"bar"> +>wrapBar('bar') : Wrap<"bar"> +>wrapBar : (value: "bar") => Wrap<"bar"> +>'bar' : "bar" + + const value2: string = 'bar'; +>value2 : string +>'bar' : "bar" + + const literal2 = wrapBar(value2); // Error +>literal2 : Wrap<"bar"> +>wrapBar(value2) : Wrap<"bar"> +>wrapBar : (value: "bar") => Wrap<"bar"> +>value2 : string + + return wrap(value); +>wrap(value) : Wrap<"bar"> +>wrap : (value: T) => Wrap +>value : "bar" +} + +function wrappedBaz(): Wrap<'baz'> { +>wrappedBaz : () => Wrap<"baz"> + + const value: 'baz' = 'baz'; +>value : "baz" +>'baz' : "baz" + + return wrap(value); +>wrap(value) : Wrap<"baz"> +>wrap : (value: T) => Wrap +>value : "baz" +} + +// Repro from #11152 + +interface FolderContentItem { + type: 'folder' | 'file'; +>type : "folder" | "file" +} + +let a: FolderContentItem[] = []; +>a : FolderContentItem[] +>[] : never[] + +a = [1, 2, 3, 4, 5].map(v => ({ type: 'folder' })); +>a = [1, 2, 3, 4, 5].map(v => ({ type: 'folder' })) : { type: "folder"; }[] +>a : FolderContentItem[] +>[1, 2, 3, 4, 5].map(v => ({ type: 'folder' })) : { type: "folder"; }[] +>[1, 2, 3, 4, 5].map : (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[] +>[1, 2, 3, 4, 5] : number[] +>1 : 1 +>2 : 2 +>3 : 3 +>4 : 4 +>5 : 5 +>map : (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[] +>v => ({ type: 'folder' }) : (v: number) => { type: "folder"; } +>v : number +>({ type: 'folder' }) : { type: "folder"; } +>{ type: 'folder' } : { type: "folder"; } +>type : "folder" +>'folder' : "folder" + +// Repro from #11312 + +let arr: Array<[number, number]> = [[1, 2]] +>arr : [number, number][] +>[[1, 2]] : [number, number][] +>[1, 2] : [number, number] +>1 : 1 +>2 : 2 + +let mappedArr: Array<[number, number]> = arr.map(([x, y]) => { +>mappedArr : [number, number][] +>arr.map(([x, y]) => { return [x, y];}) : [number, number][] +>arr.map : (callbackfn: (value: [number, number], index: number, array: [number, number][]) => U, thisArg?: any) => U[] +>arr : [number, number][] +>map : (callbackfn: (value: [number, number], index: number, array: [number, number][]) => U, thisArg?: any) => U[] +>([x, y]) => { return [x, y];} : ([x, y]: [number, number]) => [number, number] +>x : number +>y : number + + return [x, y]; +>[x, y] : [number, number] +>x : number +>y : number + +}) + +// Repro from #13594 + +export namespace DiagnosticSeverity { +>DiagnosticSeverity : typeof DiagnosticSeverity + + export const Error = 1; +>Error : 1 +>1 : 1 + + export const Warning = 2; +>Warning : 2 +>2 : 2 + + export const Information = 3; +>Information : 3 +>3 : 3 + + export const Hint = 4; +>Hint : 4 +>4 : 4 +} + +export type DiagnosticSeverity = 1 | 2 | 3 | 4; +>DiagnosticSeverity : DiagnosticSeverity + +export interface Diagnostic { + severity?: DiagnosticSeverity; +>severity : 1 | 2 | 3 | 4 | undefined + + code?: number | string; +>code : string | number | undefined + + source?: string; +>source : string | undefined + + message: string; +>message : string +} + +function bug(): Diagnostic[] { +>bug : () => Diagnostic[] + + let values: any[] = []; +>values : any[] +>[] : never[] + + return values.map((value) => { +>values.map((value) => { return { severity: DiagnosticSeverity.Error, message: 'message' } }) : { severity: 1; message: string; }[] +>values.map : (callbackfn: (value: any, index: number, array: any[]) => U, thisArg?: any) => U[] +>values : any[] +>map : (callbackfn: (value: any, index: number, array: any[]) => U, thisArg?: any) => U[] +>(value) => { return { severity: DiagnosticSeverity.Error, message: 'message' } } : (value: any) => { severity: 1; message: string; } +>value : any + + return { +>{ severity: DiagnosticSeverity.Error, message: 'message' } : { severity: 1; message: string; } + + severity: DiagnosticSeverity.Error, +>severity : 1 +>DiagnosticSeverity.Error : 1 +>DiagnosticSeverity : typeof DiagnosticSeverity +>Error : 1 + + message: 'message' +>message : string +>'message' : "message" + } + }); +} + +// Repro from #22870 + +function objectToMap(obj: any) { +>objectToMap : (obj: any) => Map +>obj : any + + return new Map(Object.keys(obj).map(key => [key, obj[key]])); +>new Map(Object.keys(obj).map(key => [key, obj[key]])) : Map +>Map : MapConstructor +>Object.keys(obj).map(key => [key, obj[key]]) : [string, any][] +>Object.keys(obj).map : (callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[] +>Object.keys(obj) : string[] +>Object.keys : (o: {}) => string[] +>Object : ObjectConstructor +>keys : (o: {}) => string[] +>obj : any +>map : (callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[] +>key => [key, obj[key]] : (key: string) => [string, any] +>key : string +>[key, obj[key]] : [string, any] +>key : string +>obj[key] : any +>obj : any +>key : string + +}; + +// Repro from #24352 + +interface Person { + phoneNumbers: { +>phoneNumbers : { __typename: "PhoneNumber"; }[] + + __typename: 'PhoneNumber'; +>__typename : "PhoneNumber" + + }[]; +} + +function createPerson(): Person { +>createPerson : () => Person + + return { +>{ phoneNumbers: [1].map(() => ({ __typename: 'PhoneNumber' })) } : { phoneNumbers: { __typename: "PhoneNumber"; }[]; } + + phoneNumbers: [1].map(() => ({ +>phoneNumbers : { __typename: "PhoneNumber"; }[] +>[1].map(() => ({ __typename: 'PhoneNumber' })) : { __typename: "PhoneNumber"; }[] +>[1].map : (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[] +>[1] : number[] +>1 : 1 +>map : (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[] +>() => ({ __typename: 'PhoneNumber' }) : () => { __typename: "PhoneNumber"; } +>({ __typename: 'PhoneNumber' }) : { __typename: "PhoneNumber"; } +>{ __typename: 'PhoneNumber' } : { __typename: "PhoneNumber"; } + + __typename: 'PhoneNumber' +>__typename : "PhoneNumber" +>'PhoneNumber' : "PhoneNumber" + + })) + }; +} + +// Repro from #26621 + +type Box = { value: T }; +>Box : Box +>value : T + +declare function box(value: T): Box; +>box : (value: T) => Box +>value : T + +type WinCondition = +>WinCondition : WinCondition + + | { type: 'win', player: string } +>type : "win" +>player : string + + | { type: 'draw' }; +>type : "draw" + +let zz: Box = box({ type: 'draw' }); +>zz : Box +>box({ type: 'draw' }) : Box<{ type: "draw"; }> +>box : (value: T) => Box +>{ type: 'draw' } : { type: "draw"; } +>type : "draw" +>'draw' : "draw" + +type WinType = 'win' | 'draw'; +>WinType : "win" | "draw" + +let yy: Box = box('draw'); +>yy : Box<"win" | "draw"> +>box('draw') : Box<"draw"> +>box : (value: T) => Box +>'draw' : "draw" + +// Repro from #27074 + +interface OK { + kind: "OK"; +>kind : "OK" + + value: T; +>value : T +} +export function ok(value: T): OK { +>ok : (value: T) => OK +>value : T + + return { +>{ kind: "OK", value: value } : { kind: "OK"; value: T; } + + kind: "OK", +>kind : "OK" +>"OK" : "OK" + + value: value +>value : T +>value : T + + }; +} + +let result: OK<[string, number]> = ok(["hello", 12]); +>result : OK<[string, number]> +>ok(["hello", 12]) : OK<[string, number]> +>ok : (value: T) => OK +>["hello", 12] : [string, number] +>"hello" : "hello" +>12 : 12 + +// Repro from #25889 + +interface I { + code: 'mapped', +>code : "mapped" + + name: string, +>name : string +} + +const a3: I[] = ['a', 'b'].map(name => { +>a3 : I[] +>['a', 'b'].map(name => { return { code: 'mapped', name, }}) : { code: "mapped"; name: string; }[] +>['a', 'b'].map : (callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[] +>['a', 'b'] : string[] +>'a' : "a" +>'b' : "b" +>map : (callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[] +>name => { return { code: 'mapped', name, }} : (name: string) => { code: "mapped"; name: string; } +>name : string + + return { +>{ code: 'mapped', name, } : { code: "mapped"; name: string; } + + code: 'mapped', +>code : "mapped" +>'mapped' : "mapped" + + name, +>name : string + } +}); + +// Repro from https://www.memsql.com/blog/porting-30k-lines-of-code-from-flow-to-typescript/ + +type Player = { +>Player : Player + + name: string; +>name : string + + age: number; +>age : number + + position: "STRIKER" | "GOALKEEPER", +>position : "STRIKER" | "GOALKEEPER" + +}; + +type F = () => Promise>; +>F : F + +const f1: F = () => { +>f1 : F +>() => { return Promise.all([ { name: "David Gomes", age: 23, position: "GOALKEEPER", }, { name: "Cristiano Ronaldo", age: 33, position: "STRIKER", } ]);} : () => Promise<[{ name: string; age: number; position: "GOALKEEPER"; }, { name: string; age: number; position: "STRIKER"; }]> + + return Promise.all([ +>Promise.all([ { name: "David Gomes", age: 23, position: "GOALKEEPER", }, { name: "Cristiano Ronaldo", age: 33, position: "STRIKER", } ]) : Promise<[{ name: string; age: number; position: "GOALKEEPER"; }, { name: string; age: number; position: "STRIKER"; }]> +>Promise.all : { (values: Iterable>): Promise; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike, T9 | PromiseLike, T10 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike, T9 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike]): Promise<[T1, T2, T3, T4, T5]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike]): Promise<[T1, T2, T3, T4]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike]): Promise<[T1, T2, T3]>; (values: [T1 | PromiseLike, T2 | PromiseLike]): Promise<[T1, T2]>; (values: (T | PromiseLike)[]): Promise; } +>Promise : PromiseConstructor +>all : { (values: Iterable>): Promise; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike, T9 | PromiseLike, T10 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike, T9 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike, T8 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike, T7 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6, T7]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike, T6 | PromiseLike]): Promise<[T1, T2, T3, T4, T5, T6]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike, T5 | PromiseLike]): Promise<[T1, T2, T3, T4, T5]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike, T4 | PromiseLike]): Promise<[T1, T2, T3, T4]>; (values: [T1 | PromiseLike, T2 | PromiseLike, T3 | PromiseLike]): Promise<[T1, T2, T3]>; (values: [T1 | PromiseLike, T2 | PromiseLike]): Promise<[T1, T2]>; (values: (T | PromiseLike)[]): Promise; } +>[ { name: "David Gomes", age: 23, position: "GOALKEEPER", }, { name: "Cristiano Ronaldo", age: 33, position: "STRIKER", } ] : [{ name: string; age: number; position: "GOALKEEPER"; }, { name: string; age: number; position: "STRIKER"; }] + { +>{ name: "David Gomes", age: 23, position: "GOALKEEPER", } : { name: string; age: number; position: "GOALKEEPER"; } + + name: "David Gomes", +>name : string +>"David Gomes" : "David Gomes" + + age: 23, +>age : number +>23 : 23 + + position: "GOALKEEPER", +>position : "GOALKEEPER" +>"GOALKEEPER" : "GOALKEEPER" + + }, { +>{ name: "Cristiano Ronaldo", age: 33, position: "STRIKER", } : { name: string; age: number; position: "STRIKER"; } + + name: "Cristiano Ronaldo", +>name : string +>"Cristiano Ronaldo" : "Cristiano Ronaldo" + + age: 33, +>age : number +>33 : 33 + + position: "STRIKER", +>position : "STRIKER" +>"STRIKER" : "STRIKER" + } + ]); +}; + From 0b366ce751784e6aaced01daa107b9c9770d2996 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 18 Jan 2019 14:47:58 -0800 Subject: [PATCH 12/22] Address CR feedback --- src/compiler/checker.ts | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f66667d2dd..c85b7457f7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17715,12 +17715,28 @@ namespace ts { if (contextualType && maybeTypeOfKind(contextualType, TypeFlags.Instantiable)) { const returnMapper = (getContextualMapper(node)).returnMapper; if (returnMapper) { - return mapType(contextualType, t => t.flags & TypeFlags.Instantiable ? instantiateType(t, returnMapper) : t); + return instantiateInstantiableTypes(contextualType, returnMapper); } } return contextualType; } + // This function is similar to instantiateType, except (a) that it only instantiates types that + // are classified as instantiable (i.e. it doesn't instantiate object types), and (b) it performs + // no reductions on instantiated union types. + function instantiateInstantiableTypes(type: Type, mapper: TypeMapper): Type { + if (type.flags & TypeFlags.Instantiable) { + return instantiateType(type, mapper); + } + if (type.flags & TypeFlags.Union) { + getUnionType(map((type).types, t => instantiateInstantiableTypes(t, mapper)), UnionReduction.None); + } + if (type.flags & TypeFlags.Intersection) { + getIntersectionType(map((type).types, t => instantiateInstantiableTypes(t, mapper))); + } + return type; + } + /** * Woah! Do you really want to use this function? * @@ -22963,6 +22979,9 @@ namespace ts { const checkMode = contextualMapper === identityMapper ? CheckMode.SkipContextSensitive : contextualMapper ? CheckMode.Inferential : CheckMode.Contextual; const type = checkExpression(node, checkMode); + // We strip literal freshness when an appropriate contextual type is present such that contextually typed + // literals always preserve their literal types (otherwise they might widen during type inference). An alternative + // here would be to not mark contextually typed literals as fresh in the first place. const result = maybeTypeOfKind(type, TypeFlags.Literal) && isLiteralOfContextualType(type, instantiateContextualType(contextualType, node)) ? getRegularTypeOfLiteralType(type) : type; context.contextualType = saveContextualType; From 0b1da02a62e3bb88611514840e6cc397ef33eab8 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 18 Jan 2019 16:02:13 -0800 Subject: [PATCH 13/22] Add missing return statements (ugh) --- src/compiler/checker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c85b7457f7..7ba3b2771c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17729,10 +17729,10 @@ namespace ts { return instantiateType(type, mapper); } if (type.flags & TypeFlags.Union) { - getUnionType(map((type).types, t => instantiateInstantiableTypes(t, mapper)), UnionReduction.None); + return getUnionType(map((type).types, t => instantiateInstantiableTypes(t, mapper)), UnionReduction.None); } if (type.flags & TypeFlags.Intersection) { - getIntersectionType(map((type).types, t => instantiateInstantiableTypes(t, mapper))); + return getIntersectionType(map((type).types, t => instantiateInstantiableTypes(t, mapper))); } return type; } From 60e7528ee642a03708f9bda31d242d69a6271132 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 20 Jan 2019 08:20:40 -0800 Subject: [PATCH 14/22] No union type reductions in contextual types --- src/compiler/checker.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7ba3b2771c..490453a6b4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17696,7 +17696,7 @@ namespace ts { function getApparentTypeOfContextualType(node: Expression): Type | undefined { const contextualType = instantiateContextualType(getContextualType(node), node); if (contextualType) { - const apparentType = mapType(contextualType, getApparentType); + const apparentType = mapType(contextualType, getApparentType, /*noReductions*/ true); if (apparentType.flags & TypeFlags.Union) { if (isObjectLiteralExpression(node)) { return discriminateContextualTypeByObjectMembers(node, apparentType as UnionType); @@ -17709,7 +17709,7 @@ namespace ts { } } - // If the given contextual type constains instantiable types and if a mapper representing + // If the given contextual type contains instantiable types and if a mapper representing // return type inferences is available, instantiate those types using that mapper. function instantiateContextualType(contextualType: Type | undefined, node: Expression): Type | undefined { if (contextualType && maybeTypeOfKind(contextualType, TypeFlags.Instantiable)) { @@ -17721,7 +17721,7 @@ namespace ts { return contextualType; } - // This function is similar to instantiateType, except (a) that it only instantiates types that + // This function is similar to instantiateType, except that (a) it only instantiates types that // are classified as instantiable (i.e. it doesn't instantiate object types), and (b) it performs // no reductions on instantiated union types. function instantiateInstantiableTypes(type: Type, mapper: TypeMapper): Type { From dbea08f9c8be9c2aab63b01cb7c7ca114805aa37 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 20 Jan 2019 08:21:26 -0800 Subject: [PATCH 15/22] Accept new baselines --- .../reference/objectLiteralExcessProperties.errors.txt | 4 ++-- tests/baselines/reference/objectLiteralExcessProperties.types | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/baselines/reference/objectLiteralExcessProperties.errors.txt b/tests/baselines/reference/objectLiteralExcessProperties.errors.txt index 4b034b0620..e4fc4d69fc 100644 --- a/tests/baselines/reference/objectLiteralExcessProperties.errors.txt +++ b/tests/baselines/reference/objectLiteralExcessProperties.errors.txt @@ -25,7 +25,7 @@ tests/cases/compiler/objectLiteralExcessProperties.ts(37,25): error TS2304: Cann tests/cases/compiler/objectLiteralExcessProperties.ts(39,11): error TS2322: Type '{ name: string; }' is not assignable to type 'T'. tests/cases/compiler/objectLiteralExcessProperties.ts(41,11): error TS2322: Type '{ name: string; prop: boolean; }' is not assignable to type 'T & { prop: boolean; }'. Type '{ name: string; prop: boolean; }' is not assignable to type 'T'. -tests/cases/compiler/objectLiteralExcessProperties.ts(43,43): error TS2322: Type '{ name: string; prop: boolean; }' is not assignable to type 'T | { prop: boolean; }'. +tests/cases/compiler/objectLiteralExcessProperties.ts(43,43): error TS2322: Type '{ name: string; prop: true; }' is not assignable to type 'T | { prop: boolean; }'. Object literal may only specify known properties, and 'name' does not exist in type '{ prop: boolean; }'. tests/cases/compiler/objectLiteralExcessProperties.ts(45,76): error TS2322: Type '{ name: string; prop: boolean; }' is not assignable to type '{ name: string; } | (T & { prop: boolean; })'. Object literal may only specify known properties, and 'prop' does not exist in type '{ name: string; }'. @@ -119,7 +119,7 @@ tests/cases/compiler/objectLiteralExcessProperties.ts(49,44): error TS2322: Type // Excess property checks only on non-generic parts of unions const obj3: T | { prop: boolean } = { name: "test", prop: true }; ~~~~~~~~~~~~ -!!! error TS2322: Type '{ name: string; prop: boolean; }' is not assignable to type 'T | { prop: boolean; }'. +!!! error TS2322: Type '{ name: string; prop: true; }' is not assignable to type 'T | { prop: boolean; }'. !!! error TS2322: Object literal may only specify known properties, and 'name' does not exist in type '{ prop: boolean; }'. // Excess property checks only on non-generic parts of unions const obj4: T & { prop: boolean } | { name: string } = { name: "test", prop: true }; diff --git a/tests/baselines/reference/objectLiteralExcessProperties.types b/tests/baselines/reference/objectLiteralExcessProperties.types index 8765432ab7..812f48c890 100644 --- a/tests/baselines/reference/objectLiteralExcessProperties.types +++ b/tests/baselines/reference/objectLiteralExcessProperties.types @@ -124,10 +124,10 @@ function test() { const obj3: T | { prop: boolean } = { name: "test", prop: true }; >obj3 : T | { prop: boolean; } >prop : boolean ->{ name: "test", prop: true } : { name: string; prop: boolean; } +>{ name: "test", prop: true } : { name: string; prop: true; } >name : string >"test" : "test" ->prop : boolean +>prop : true >true : true // Excess property checks only on non-generic parts of unions From cf479fc384bad6f171927a4334954331d076003c Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 20 Jan 2019 08:21:41 -0800 Subject: [PATCH 16/22] Add regression test for #29168 --- .../compiler/contextualTypeShouldBeLiteral.ts | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/tests/cases/compiler/contextualTypeShouldBeLiteral.ts b/tests/cases/compiler/contextualTypeShouldBeLiteral.ts index 1012c567a7..5da49215f5 100644 --- a/tests/cases/compiler/contextualTypeShouldBeLiteral.ts +++ b/tests/cases/compiler/contextualTypeShouldBeLiteral.ts @@ -93,4 +93,30 @@ let xyz: LikeA | LikeB = { } }; -xyz; \ No newline at end of file +xyz; + +// Repro from #29168 + +interface TestObject { + type?: 'object'; + items: { + [k: string]: TestGeneric; + }; +} + +interface TestString { + type: 'string'; +} + +type TestGeneric = (TestString | TestObject) & { [k: string]: any; }; + +const test: TestGeneric = { + items: { + hello: { type: 'string' }, + world: { + items: { + nested: { type: 'string' } + } + } + } +}; From 2ea02517091efd421e9085af8154a8cb1e3db741 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 20 Jan 2019 08:21:49 -0800 Subject: [PATCH 17/22] Accept new baselines --- .../contextualTypeShouldBeLiteral.js | 39 ++++++++++++- .../contextualTypeShouldBeLiteral.symbols | 56 +++++++++++++++++++ .../contextualTypeShouldBeLiteral.types | 56 +++++++++++++++++++ 3 files changed, 150 insertions(+), 1 deletion(-) diff --git a/tests/baselines/reference/contextualTypeShouldBeLiteral.js b/tests/baselines/reference/contextualTypeShouldBeLiteral.js index dcb9da993c..727609a5ab 100644 --- a/tests/baselines/reference/contextualTypeShouldBeLiteral.js +++ b/tests/baselines/reference/contextualTypeShouldBeLiteral.js @@ -93,7 +93,34 @@ let xyz: LikeA | LikeB = { } }; -xyz; +xyz; + +// Repro from #29168 + +interface TestObject { + type?: 'object'; + items: { + [k: string]: TestGeneric; + }; +} + +interface TestString { + type: 'string'; +} + +type TestGeneric = (TestString | TestObject) & { [k: string]: any; }; + +const test: TestGeneric = { + items: { + hello: { type: 'string' }, + world: { + items: { + nested: { type: 'string' } + } + } + } +}; + //// [contextualTypeShouldBeLiteral.js] "use strict"; @@ -134,3 +161,13 @@ var xyz = { } }; xyz; +var test = { + items: { + hello: { type: 'string' }, + world: { + items: { + nested: { type: 'string' } + } + } + } +}; diff --git a/tests/baselines/reference/contextualTypeShouldBeLiteral.symbols b/tests/baselines/reference/contextualTypeShouldBeLiteral.symbols index 314117b509..a38443d4b0 100644 --- a/tests/baselines/reference/contextualTypeShouldBeLiteral.symbols +++ b/tests/baselines/reference/contextualTypeShouldBeLiteral.symbols @@ -227,3 +227,59 @@ let xyz: LikeA | LikeB = { xyz; >xyz : Symbol(xyz, Decl(contextualTypeShouldBeLiteral.ts, 82, 3)) +// Repro from #29168 + +interface TestObject { +>TestObject : Symbol(TestObject, Decl(contextualTypeShouldBeLiteral.ts, 94, 4)) + + type?: 'object'; +>type : Symbol(TestObject.type, Decl(contextualTypeShouldBeLiteral.ts, 98, 22)) + + items: { +>items : Symbol(TestObject.items, Decl(contextualTypeShouldBeLiteral.ts, 99, 18)) + + [k: string]: TestGeneric; +>k : Symbol(k, Decl(contextualTypeShouldBeLiteral.ts, 101, 5)) +>TestGeneric : Symbol(TestGeneric, Decl(contextualTypeShouldBeLiteral.ts, 107, 1)) + + }; +} + +interface TestString { +>TestString : Symbol(TestString, Decl(contextualTypeShouldBeLiteral.ts, 103, 1)) + + type: 'string'; +>type : Symbol(TestString.type, Decl(contextualTypeShouldBeLiteral.ts, 105, 22)) +} + +type TestGeneric = (TestString | TestObject) & { [k: string]: any; }; +>TestGeneric : Symbol(TestGeneric, Decl(contextualTypeShouldBeLiteral.ts, 107, 1)) +>TestString : Symbol(TestString, Decl(contextualTypeShouldBeLiteral.ts, 103, 1)) +>TestObject : Symbol(TestObject, Decl(contextualTypeShouldBeLiteral.ts, 94, 4)) +>k : Symbol(k, Decl(contextualTypeShouldBeLiteral.ts, 109, 50)) + +const test: TestGeneric = { +>test : Symbol(test, Decl(contextualTypeShouldBeLiteral.ts, 111, 5)) +>TestGeneric : Symbol(TestGeneric, Decl(contextualTypeShouldBeLiteral.ts, 107, 1)) + + items: { +>items : Symbol(items, Decl(contextualTypeShouldBeLiteral.ts, 111, 27)) + + hello: { type: 'string' }, +>hello : Symbol(hello, Decl(contextualTypeShouldBeLiteral.ts, 112, 10)) +>type : Symbol(type, Decl(contextualTypeShouldBeLiteral.ts, 113, 12)) + + world: { +>world : Symbol(world, Decl(contextualTypeShouldBeLiteral.ts, 113, 30)) + + items: { +>items : Symbol(items, Decl(contextualTypeShouldBeLiteral.ts, 114, 12)) + + nested: { type: 'string' } +>nested : Symbol(nested, Decl(contextualTypeShouldBeLiteral.ts, 115, 14)) +>type : Symbol(type, Decl(contextualTypeShouldBeLiteral.ts, 116, 17)) + } + } + } +}; + diff --git a/tests/baselines/reference/contextualTypeShouldBeLiteral.types b/tests/baselines/reference/contextualTypeShouldBeLiteral.types index a5867f0de4..d9795c7e33 100644 --- a/tests/baselines/reference/contextualTypeShouldBeLiteral.types +++ b/tests/baselines/reference/contextualTypeShouldBeLiteral.types @@ -222,3 +222,59 @@ let xyz: LikeA | LikeB = { xyz; >xyz : LikeA +// Repro from #29168 + +interface TestObject { + type?: 'object'; +>type : "object" | undefined + + items: { +>items : { [k: string]: TestGeneric; } + + [k: string]: TestGeneric; +>k : string + + }; +} + +interface TestString { + type: 'string'; +>type : "string" +} + +type TestGeneric = (TestString | TestObject) & { [k: string]: any; }; +>TestGeneric : TestGeneric +>k : string + +const test: TestGeneric = { +>test : TestGeneric +>{ items: { hello: { type: 'string' }, world: { items: { nested: { type: 'string' } } } }} : { items: { hello: { type: "string"; }; world: { items: { nested: { type: "string"; }; }; }; }; } + + items: { +>items : { hello: { type: "string"; }; world: { items: { nested: { type: "string"; }; }; }; } +>{ hello: { type: 'string' }, world: { items: { nested: { type: 'string' } } } } : { hello: { type: "string"; }; world: { items: { nested: { type: "string"; }; }; }; } + + hello: { type: 'string' }, +>hello : { type: "string"; } +>{ type: 'string' } : { type: "string"; } +>type : "string" +>'string' : "string" + + world: { +>world : { items: { nested: { type: "string"; }; }; } +>{ items: { nested: { type: 'string' } } } : { items: { nested: { type: "string"; }; }; } + + items: { +>items : { nested: { type: "string"; }; } +>{ nested: { type: 'string' } } : { nested: { type: "string"; }; } + + nested: { type: 'string' } +>nested : { type: "string"; } +>{ type: 'string' } : { type: "string"; } +>type : "string" +>'string' : "string" + } + } + } +}; + From ddbac8f3fe87bb6044ceab2f68eacd81d7dd6977 Mon Sep 17 00:00:00 2001 From: xiaofa Date: Sat, 26 Jan 2019 23:59:32 +0800 Subject: [PATCH 18/22] get appropriate parent jsdoc node for arrow functions --- src/services/codefixes/inferFromUsage.ts | 12 +++++++++++- src/services/textChanges.ts | 4 +--- .../fourslash/codeFixInferFromUsageArrowJS.ts | 17 +++++++++++++---- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/services/codefixes/inferFromUsage.ts b/src/services/codefixes/inferFromUsage.ts index 8e5b962116..f47f618f79 100644 --- a/src/services/codefixes/inferFromUsage.ts +++ b/src/services/codefixes/inferFromUsage.ts @@ -274,7 +274,17 @@ namespace ts.codefix { return !!merged; })); const tag = createJSDocComment(comments.join("\n"), createNodeArray([...(oldTags || emptyArray), ...unmergedNewTags])); - changes.insertJsdocCommentBefore(sourceFile, parent, tag); + const jsDocNode = parent.kind === SyntaxKind.ArrowFunction ? getJsDocNodeForArrowFunction(parent) : parent; + jsDocNode.jsDoc = parent.jsDoc; + jsDocNode.jsDocCache = parent.jsDocCache; + changes.insertJsdocCommentBefore(sourceFile, jsDocNode, tag); + } + + function getJsDocNodeForArrowFunction(signature: ArrowFunction): HasJSDoc { + if (signature.parent.kind === SyntaxKind.PropertyDeclaration) { + return signature.parent; + } + return signature.parent.parent; } function tryMergeJsdocTags(oldTag: JSDocTag, newTag: JSDocTag): JSDocTag | undefined { diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index 7dab720584..4689e18508 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -340,9 +340,7 @@ namespace ts.textChanges { } public insertJsdocCommentBefore(sourceFile: SourceFile, node: HasJSDoc, tag: JSDoc): void { - const fnStart = node.kind === SyntaxKind.ArrowFunction - ? node.parent.parent.getStart(sourceFile) - : node.getStart(sourceFile); + const fnStart = node.getStart(sourceFile); if (node.jsDoc) { for (const jsdoc of node.jsDoc) { this.deleteRange(sourceFile, { diff --git a/tests/cases/fourslash/codeFixInferFromUsageArrowJS.ts b/tests/cases/fourslash/codeFixInferFromUsageArrowJS.ts index e867ae99c7..0a800fd7d6 100644 --- a/tests/cases/fourslash/codeFixInferFromUsageArrowJS.ts +++ b/tests/cases/fourslash/codeFixInferFromUsageArrowJS.ts @@ -6,13 +6,22 @@ // @Filename: test.js ////const foo = x => x.y + 1; +////class C { +//// m = x => x.y + 1; +////} -verify.codeFix({ - description: "Infer parameter types from usage", - index: 0, +verify.codeFixAll({ + fixId: "inferFromUsage", + fixAllDescription: "Infer all types from usage", newFileContent: `/** * @param {{ y: number; }} x */ -const foo = x => x.y + 1;`, +const foo = x => x.y + 1; +class C { + /** + * @param {{ y: number; }} x + */ + m = x => x.y + 1; +}`, }); \ No newline at end of file From c58157573e863e4a9838cbd7a62874e06e8f7b2b Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 1 Feb 2019 10:48:52 -0800 Subject: [PATCH 19/22] Add breaking change repros --- .../compiler/inferFromGenericFunctionReturnTypes3.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts b/tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts index e44e7c4a5e..429d98b6a3 100644 --- a/tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts +++ b/tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts @@ -172,3 +172,13 @@ const f1: F = () => { } ]); }; + +// Breaking change repros from #29478 + +declare function foldLeft(z: U, f: (acc: U, t: boolean) => U): U; +let res: boolean = foldLeft(true, (acc, t) => acc && t); // Error + +enum State { A, B } +type Foo = { state: State } +declare function bar(f: () => T[]): T[]; +let x: Foo[] = bar(() => !!true ? [{ state: State.A }] : [{ state: State.B }]); // Error From 42be36d1826eccd6686906e0c74c2de118083ffd Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 1 Feb 2019 10:48:58 -0800 Subject: [PATCH 20/22] Accept new baselines --- ...FromGenericFunctionReturnTypes3.errors.txt | 28 +++++++++- .../inferFromGenericFunctionReturnTypes3.js | 17 ++++++ ...ferFromGenericFunctionReturnTypes3.symbols | 52 +++++++++++++++++ ...inferFromGenericFunctionReturnTypes3.types | 56 +++++++++++++++++++ 4 files changed, 152 insertions(+), 1 deletion(-) diff --git a/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.errors.txt b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.errors.txt index 9a0d64c1a5..7c79c63f78 100644 --- a/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.errors.txt +++ b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.errors.txt @@ -1,7 +1,13 @@ tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts(28,30): error TS2345: Argument of type 'string' is not assignable to parameter of type '"bar"'. +tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts(175,47): error TS2322: Type 'boolean' is not assignable to type 'true'. +tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts(180,26): error TS2322: Type '{ state: State.A; }[] | { state: State.B; }[]' is not assignable to type '{ state: State.A; }[]'. + Type '{ state: State.B; }[]' is not assignable to type '{ state: State.A; }[]'. + Type '{ state: State.B; }' is not assignable to type '{ state: State.A; }'. + Types of property 'state' are incompatible. + Type 'State.B' is not assignable to type 'State.A'. -==== tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts (1 errors) ==== +==== tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts (3 errors) ==== // Repros from #5487 function truePromise(): Promise { @@ -174,4 +180,24 @@ tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts(28,30): error TS234 } ]); }; + + // Breaking change repros from #29478 + + declare function foldLeft(z: U, f: (acc: U, t: boolean) => U): U; + let res: boolean = foldLeft(true, (acc, t) => acc && t); // Error + ~~~~~~~~ +!!! error TS2322: Type 'boolean' is not assignable to type 'true'. +!!! related TS6502 tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts:174:39: The expected type comes from the return type of this signature. + + enum State { A, B } + type Foo = { state: State } + declare function bar(f: () => T[]): T[]; + let x: Foo[] = bar(() => !!true ? [{ state: State.A }] : [{ state: State.B }]); // Error + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ state: State.A; }[] | { state: State.B; }[]' is not assignable to type '{ state: State.A; }[]'. +!!! error TS2322: Type '{ state: State.B; }[]' is not assignable to type '{ state: State.A; }[]'. +!!! error TS2322: Type '{ state: State.B; }' is not assignable to type '{ state: State.A; }'. +!!! error TS2322: Types of property 'state' are incompatible. +!!! error TS2322: Type 'State.B' is not assignable to type 'State.A'. +!!! related TS6502 tests/cases/compiler/inferFromGenericFunctionReturnTypes3.ts:179:28: The expected type comes from the return type of this signature. \ No newline at end of file diff --git a/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.js b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.js index ca1533bbab..99070e6ddc 100644 --- a/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.js +++ b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.js @@ -169,6 +169,16 @@ const f1: F = () => { } ]); }; + +// Breaking change repros from #29478 + +declare function foldLeft(z: U, f: (acc: U, t: boolean) => U): U; +let res: boolean = foldLeft(true, (acc, t) => acc && t); // Error + +enum State { A, B } +type Foo = { state: State } +declare function bar(f: () => T[]): T[]; +let x: Foo[] = bar(() => !!true ? [{ state: State.A }] : [{ state: State.B }]); // Error //// [inferFromGenericFunctionReturnTypes3.js] @@ -261,6 +271,13 @@ const f1 = () => { } ]); }; +let res = foldLeft(true, (acc, t) => acc && t); // Error +var State; +(function (State) { + State[State["A"] = 0] = "A"; + State[State["B"] = 1] = "B"; +})(State || (State = {})); +let x = bar(() => !!true ? [{ state: State.A }] : [{ state: State.B }]); // Error //// [inferFromGenericFunctionReturnTypes3.d.ts] diff --git a/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.symbols b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.symbols index 16beb0546d..7281886e62 100644 --- a/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.symbols +++ b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.symbols @@ -407,3 +407,55 @@ const f1: F = () => { ]); }; +// Breaking change repros from #29478 + +declare function foldLeft(z: U, f: (acc: U, t: boolean) => U): U; +>foldLeft : Symbol(foldLeft, Decl(inferFromGenericFunctionReturnTypes3.ts, 169, 2)) +>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes3.ts, 173, 26)) +>z : Symbol(z, Decl(inferFromGenericFunctionReturnTypes3.ts, 173, 29)) +>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes3.ts, 173, 26)) +>f : Symbol(f, Decl(inferFromGenericFunctionReturnTypes3.ts, 173, 34)) +>acc : Symbol(acc, Decl(inferFromGenericFunctionReturnTypes3.ts, 173, 39)) +>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes3.ts, 173, 26)) +>t : Symbol(t, Decl(inferFromGenericFunctionReturnTypes3.ts, 173, 46)) +>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes3.ts, 173, 26)) +>U : Symbol(U, Decl(inferFromGenericFunctionReturnTypes3.ts, 173, 26)) + +let res: boolean = foldLeft(true, (acc, t) => acc && t); // Error +>res : Symbol(res, Decl(inferFromGenericFunctionReturnTypes3.ts, 174, 3)) +>foldLeft : Symbol(foldLeft, Decl(inferFromGenericFunctionReturnTypes3.ts, 169, 2)) +>acc : Symbol(acc, Decl(inferFromGenericFunctionReturnTypes3.ts, 174, 35)) +>t : Symbol(t, Decl(inferFromGenericFunctionReturnTypes3.ts, 174, 39)) +>acc : Symbol(acc, Decl(inferFromGenericFunctionReturnTypes3.ts, 174, 35)) +>t : Symbol(t, Decl(inferFromGenericFunctionReturnTypes3.ts, 174, 39)) + +enum State { A, B } +>State : Symbol(State, Decl(inferFromGenericFunctionReturnTypes3.ts, 174, 56)) +>A : Symbol(State.A, Decl(inferFromGenericFunctionReturnTypes3.ts, 176, 12)) +>B : Symbol(State.B, Decl(inferFromGenericFunctionReturnTypes3.ts, 176, 15)) + +type Foo = { state: State } +>Foo : Symbol(Foo, Decl(inferFromGenericFunctionReturnTypes3.ts, 176, 19)) +>state : Symbol(state, Decl(inferFromGenericFunctionReturnTypes3.ts, 177, 12)) +>State : Symbol(State, Decl(inferFromGenericFunctionReturnTypes3.ts, 174, 56)) + +declare function bar(f: () => T[]): T[]; +>bar : Symbol(bar, Decl(inferFromGenericFunctionReturnTypes3.ts, 177, 27)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 178, 21)) +>f : Symbol(f, Decl(inferFromGenericFunctionReturnTypes3.ts, 178, 24)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 178, 21)) +>T : Symbol(T, Decl(inferFromGenericFunctionReturnTypes3.ts, 178, 21)) + +let x: Foo[] = bar(() => !!true ? [{ state: State.A }] : [{ state: State.B }]); // Error +>x : Symbol(x, Decl(inferFromGenericFunctionReturnTypes3.ts, 179, 3)) +>Foo : Symbol(Foo, Decl(inferFromGenericFunctionReturnTypes3.ts, 176, 19)) +>bar : Symbol(bar, Decl(inferFromGenericFunctionReturnTypes3.ts, 177, 27)) +>state : Symbol(state, Decl(inferFromGenericFunctionReturnTypes3.ts, 179, 36)) +>State.A : Symbol(State.A, Decl(inferFromGenericFunctionReturnTypes3.ts, 176, 12)) +>State : Symbol(State, Decl(inferFromGenericFunctionReturnTypes3.ts, 174, 56)) +>A : Symbol(State.A, Decl(inferFromGenericFunctionReturnTypes3.ts, 176, 12)) +>state : Symbol(state, Decl(inferFromGenericFunctionReturnTypes3.ts, 179, 59)) +>State.B : Symbol(State.B, Decl(inferFromGenericFunctionReturnTypes3.ts, 176, 15)) +>State : Symbol(State, Decl(inferFromGenericFunctionReturnTypes3.ts, 174, 56)) +>B : Symbol(State.B, Decl(inferFromGenericFunctionReturnTypes3.ts, 176, 15)) + diff --git a/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.types b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.types index e983cc6481..ccbeb99a11 100644 --- a/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.types +++ b/tests/baselines/reference/inferFromGenericFunctionReturnTypes3.types @@ -450,3 +450,59 @@ const f1: F = () => { ]); }; +// Breaking change repros from #29478 + +declare function foldLeft(z: U, f: (acc: U, t: boolean) => U): U; +>foldLeft : (z: U, f: (acc: U, t: boolean) => U) => U +>z : U +>f : (acc: U, t: boolean) => U +>acc : U +>t : boolean + +let res: boolean = foldLeft(true, (acc, t) => acc && t); // Error +>res : boolean +>foldLeft(true, (acc, t) => acc && t) : any +>foldLeft : (z: U, f: (acc: U, t: boolean) => U) => U +>true : true +>(acc, t) => acc && t : (acc: true, t: boolean) => boolean +>acc : true +>t : boolean +>acc && t : boolean +>acc : true +>t : boolean + +enum State { A, B } +>State : State +>A : State.A +>B : State.B + +type Foo = { state: State } +>Foo : Foo +>state : State + +declare function bar(f: () => T[]): T[]; +>bar : (f: () => T[]) => T[] +>f : () => T[] + +let x: Foo[] = bar(() => !!true ? [{ state: State.A }] : [{ state: State.B }]); // Error +>x : Foo[] +>bar(() => !!true ? [{ state: State.A }] : [{ state: State.B }]) : any +>bar : (f: () => T[]) => T[] +>() => !!true ? [{ state: State.A }] : [{ state: State.B }] : () => { state: State.A; }[] | { state: State.B; }[] +>!!true ? [{ state: State.A }] : [{ state: State.B }] : { state: State; }[] +>!!true : true +>!true : false +>true : true +>[{ state: State.A }] : { state: State; }[] +>{ state: State.A } : { state: State; } +>state : State +>State.A : State.A +>State : typeof State +>A : State.A +>[{ state: State.B }] : { state: State; }[] +>{ state: State.B } : { state: State; } +>state : State +>State.B : State.B +>State : typeof State +>B : State.B + From 30fa6d08cc5da961632037bab4bc4f2355c32aa5 Mon Sep 17 00:00:00 2001 From: Jack Williams Date: Sun, 3 Feb 2019 16:49:52 +0000 Subject: [PATCH 21/22] Update baselines for types affected by JSON change --- .../destructuringInitializerContextualTypeFromContext.types | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/destructuringInitializerContextualTypeFromContext.types b/tests/baselines/reference/destructuringInitializerContextualTypeFromContext.types index 4018d4bed3..d0ddb4918a 100644 --- a/tests/baselines/reference/destructuringInitializerContextualTypeFromContext.types +++ b/tests/baselines/reference/destructuringInitializerContextualTypeFromContext.types @@ -50,9 +50,9 @@ const Child: SFC = ({ >`name: ${name} props: ${JSON.stringify(props)}` : string >name : "Apollo" | "Artemis" | "Dionysus" | "Persephone" >JSON.stringify(props) : string ->JSON.stringify : { (value: any, replacer?: ((key: string, value: any) => any) | undefined, space?: string | number | undefined): string; (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string; } +>JSON.stringify : { (value: any, replacer?: ((this: any, key: string, value: any) => any) | undefined, space?: string | number | undefined): string; (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string; } >JSON : JSON ->stringify : { (value: any, replacer?: ((key: string, value: any) => any) | undefined, space?: string | number | undefined): string; (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string; } +>stringify : { (value: any, replacer?: ((this: any, key: string, value: any) => any) | undefined, space?: string | number | undefined): string; (value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string; } >props : {} // Repro from #29189 From 530a09a6e235a104b4ff483f1bbd766a5f686277 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Mon, 4 Feb 2019 07:55:39 -0800 Subject: [PATCH 22/22] Update user baselines (#29682) --- tests/baselines/reference/user/assert.log | 20 +++++++++---------- tests/baselines/reference/user/async.log | 2 +- .../reference/user/create-react-app.log | 16 +++++++-------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/tests/baselines/reference/user/assert.log b/tests/baselines/reference/user/assert.log index 87f6ac257b..672c147428 100644 --- a/tests/baselines/reference/user/assert.log +++ b/tests/baselines/reference/user/assert.log @@ -25,17 +25,17 @@ node_modules/assert/test.js(143,10): error TS2339: Property 'a' does not exist o node_modules/assert/test.js(149,5): error TS2552: Cannot find name 'test'. Did you mean 'tests'? node_modules/assert/test.js(157,51): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'never' has no compatible call signatures. node_modules/assert/test.js(161,5): error TS2552: Cannot find name 'test'. Did you mean 'tests'? -node_modules/assert/test.js(168,5): error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. -node_modules/assert/test.js(182,5): error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. -node_modules/assert/test.js(229,5): error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. -node_modules/assert/test.js(235,5): error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. -node_modules/assert/test.js(250,5): error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. -node_modules/assert/test.js(254,5): error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. +node_modules/assert/test.js(168,5): error TS2593: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. +node_modules/assert/test.js(182,5): error TS2593: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. +node_modules/assert/test.js(229,5): error TS2593: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. +node_modules/assert/test.js(235,5): error TS2593: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. +node_modules/assert/test.js(250,5): error TS2593: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. +node_modules/assert/test.js(254,5): error TS2593: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. node_modules/assert/test.js(256,55): error TS2345: Argument of type 'TypeError' is not assignable to parameter of type 'string'. -node_modules/assert/test.js(262,5): error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. -node_modules/assert/test.js(279,5): error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. -node_modules/assert/test.js(285,5): error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. -node_modules/assert/test.js(320,5): error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. +node_modules/assert/test.js(262,5): error TS2593: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. +node_modules/assert/test.js(279,5): error TS2593: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. +node_modules/assert/test.js(285,5): error TS2593: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. +node_modules/assert/test.js(320,5): error TS2593: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. diff --git a/tests/baselines/reference/user/async.log b/tests/baselines/reference/user/async.log index 286b1102af..1477ce5faa 100644 --- a/tests/baselines/reference/user/async.log +++ b/tests/baselines/reference/user/async.log @@ -51,7 +51,7 @@ node_modules/async/autoInject.js(160,28): error TS2695: Left side of comma opera node_modules/async/autoInject.js(164,14): error TS2695: Left side of comma operator is unused and has no side effects. node_modules/async/autoInject.js(168,6): error TS2695: Left side of comma operator is unused and has no side effects. node_modules/async/cargo.js(62,12): error TS2304: Cannot find name 'AsyncFunction'. -node_modules/async/cargo.js(67,14): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node` and then add `node` to the types field in your tsconfig. +node_modules/async/cargo.js(67,14): error TS2591: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node` and then add `node` to the types field in your tsconfig. node_modules/async/cargo.js(67,20): error TS1005: '}' expected. node_modules/async/cargo.js(92,11): error TS2695: Left side of comma operator is unused and has no side effects. node_modules/async/compose.js(8,37): error TS2695: Left side of comma operator is unused and has no side effects. diff --git a/tests/baselines/reference/user/create-react-app.log b/tests/baselines/reference/user/create-react-app.log index 275a3140de..1b8a132fc3 100644 --- a/tests/baselines/reference/user/create-react-app.log +++ b/tests/baselines/reference/user/create-react-app.log @@ -15,9 +15,9 @@ packages/babel-preset-react-app/index.js(123,17): error TS2307: Cannot find modu packages/babel-preset-react-app/index.js(130,17): error TS2307: Cannot find module '@babel/plugin-transform-regenerator'. packages/babel-preset-react-app/index.js(137,15): error TS2307: Cannot find module '@babel/plugin-syntax-dynamic-import'. packages/babel-preset-react-app/index.js(140,17): error TS2307: Cannot find module 'babel-plugin-transform-dynamic-import'. -packages/confusing-browser-globals/test.js(14,1): error TS2582: Cannot find name 'it'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. +packages/confusing-browser-globals/test.js(14,1): error TS2593: Cannot find name 'it'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. packages/confusing-browser-globals/test.js(15,3): error TS2304: Cannot find name 'expect'. -packages/confusing-browser-globals/test.js(18,1): error TS2582: Cannot find name 'it'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. +packages/confusing-browser-globals/test.js(18,1): error TS2593: Cannot find name 'it'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. packages/confusing-browser-globals/test.js(19,3): error TS2304: Cannot find name 'expect'. packages/create-react-app/createReactApp.js(37,37): error TS2307: Cannot find module 'validate-npm-package-name'. packages/create-react-app/createReactApp.js(47,24): error TS2307: Cannot find module 'tar-pack'. @@ -35,18 +35,18 @@ packages/react-dev-utils/FileSizeReporter.js(16,24): error TS2307: Cannot find m packages/react-dev-utils/WebpackDevServerUtils.js(9,25): error TS2307: Cannot find module 'address'. packages/react-dev-utils/WebpackDevServerUtils.js(14,24): error TS2307: Cannot find module 'detect-port-alt'. packages/react-dev-utils/WebpackDevServerUtils.js(15,24): error TS2307: Cannot find module 'is-root'. -packages/react-dev-utils/__tests__/ignoredFiles.test.js(12,1): error TS2582: Cannot find name 'describe'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. -packages/react-dev-utils/__tests__/ignoredFiles.test.js(13,3): error TS2582: Cannot find name 'it'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. +packages/react-dev-utils/__tests__/ignoredFiles.test.js(12,1): error TS2593: Cannot find name 'describe'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. +packages/react-dev-utils/__tests__/ignoredFiles.test.js(13,3): error TS2593: Cannot find name 'it'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. packages/react-dev-utils/__tests__/ignoredFiles.test.js(18,5): error TS2304: Cannot find name 'expect'. packages/react-dev-utils/__tests__/ignoredFiles.test.js(19,5): error TS2304: Cannot find name 'expect'. -packages/react-dev-utils/__tests__/ignoredFiles.test.js(22,3): error TS2582: Cannot find name 'it'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. +packages/react-dev-utils/__tests__/ignoredFiles.test.js(22,3): error TS2593: Cannot find name 'it'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. packages/react-dev-utils/__tests__/ignoredFiles.test.js(26,5): error TS2304: Cannot find name 'expect'. -packages/react-dev-utils/__tests__/ignoredFiles.test.js(29,3): error TS2582: Cannot find name 'it'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. +packages/react-dev-utils/__tests__/ignoredFiles.test.js(29,3): error TS2593: Cannot find name 'it'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. packages/react-dev-utils/__tests__/ignoredFiles.test.js(36,5): error TS2304: Cannot find name 'expect'. packages/react-dev-utils/__tests__/ignoredFiles.test.js(37,5): error TS2304: Cannot find name 'expect'. -packages/react-dev-utils/__tests__/ignoredFiles.test.js(40,3): error TS2582: Cannot find name 'it'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. +packages/react-dev-utils/__tests__/ignoredFiles.test.js(40,3): error TS2593: Cannot find name 'it'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. packages/react-dev-utils/__tests__/ignoredFiles.test.js(46,5): error TS2304: Cannot find name 'expect'. -packages/react-dev-utils/__tests__/ignoredFiles.test.js(49,3): error TS2582: Cannot find name 'it'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. +packages/react-dev-utils/__tests__/ignoredFiles.test.js(49,3): error TS2593: Cannot find name 'it'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha` and then add `jest` or `mocha` to the types field in your tsconfig. packages/react-dev-utils/__tests__/ignoredFiles.test.js(53,5): error TS2304: Cannot find name 'expect'. packages/react-dev-utils/browsersHelper.js(9,30): error TS2307: Cannot find module 'browserslist'. packages/react-dev-utils/browsersHelper.js(13,23): error TS2307: Cannot find module 'pkg-up'.