From b65a422c7a53528916eea9b43cb57e7ff91e886b Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 15 Dec 2014 14:11:21 -0800 Subject: [PATCH 1/7] Fixed contextual typing for tagged template expressions. --- src/compiler/checker.ts | 27 +++- .../taggedTemplateContextualTyping.js | 45 +++++++ .../taggedTemplateContextualTyping.types | 124 ++++++++++++++++++ .../taggedTemplateContextualTyping.ts | 22 ++++ ...TypedFunctionInTaggedTemplateExpression.ts | 44 +++++++ 5 files changed, 255 insertions(+), 7 deletions(-) create mode 100644 tests/baselines/reference/taggedTemplateContextualTyping.js create mode 100644 tests/baselines/reference/taggedTemplateContextualTyping.types create mode 100644 tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping.ts create mode 100644 tests/cases/fourslash/quickInfoForContextuallyTypedFunctionInTaggedTemplateExpression.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 889b387d4f4..502b87c0c9d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4813,17 +4813,25 @@ module ts { return undefined; } - // In a typed function call, an argument expression is contextually typed by the type of the corresponding parameter. - function getContextualTypeForArgument(node: Expression): Type { - var callExpression = node.parent; - var argIndex = indexOf(callExpression.arguments, node); + // In a typed function call, an argument or substitution expression is contextually typed by the type of the corresponding parameter. + function getContextualTypeForArgument(callTarget: CallLikeExpression, arg: Expression): Type { + var args = getEffectiveCallArguments(callTarget); + var argIndex = indexOf(args, arg); if (argIndex >= 0) { - var signature = getResolvedSignature(callExpression); + var signature = getResolvedSignature(callTarget); return getTypeAtPosition(signature, argIndex); } return undefined; } + function getContextualTypeForSubstitutionExpression(template: TemplateExpression, substitutionExpression: Expression) { + if (template.parent.kind === SyntaxKind.TaggedTemplateExpression) { + return getContextualTypeForArgument(template.parent, substitutionExpression); + } + + return undefined; + } + function getContextualTypeForBinaryOperand(node: Expression): Type { var binaryExpression = node.parent; var operator = binaryExpression.operator; @@ -4959,7 +4967,7 @@ module ts { return getContextualTypeForReturnExpression(node); case SyntaxKind.CallExpression: case SyntaxKind.NewExpression: - return getContextualTypeForArgument(node); + return getContextualTypeForArgument(parent, node); case SyntaxKind.TypeAssertionExpression: return getTypeFromTypeNode((parent).type); case SyntaxKind.BinaryExpression: @@ -4970,6 +4978,11 @@ module ts { return getContextualTypeForElementExpression(node); case SyntaxKind.ConditionalExpression: return getContextualTypeForConditionalOperand(node); + case SyntaxKind.TemplateExpression: + return getContextualTypeForSubstitutionExpression(parent.parent, node); + case SyntaxKind.TemplateSpan: + Debug.assert(parent.parent.kind === SyntaxKind.TemplateExpression); + return getContextualTypeForSubstitutionExpression(parent.parent, node); } return undefined; } @@ -5571,7 +5584,7 @@ module ts { } /** - * Returns the effective arguments for an expression that works like a function invokation. + * Returns the effective arguments for an expression that works like a function invocation. * * If 'node' is a CallExpression or a NewExpression, then its argument list is returned. * If 'node' is a TaggedTemplateExpression, a new argument list is constructed from the substitution diff --git a/tests/baselines/reference/taggedTemplateContextualTyping.js b/tests/baselines/reference/taggedTemplateContextualTyping.js new file mode 100644 index 00000000000..64b43031c76 --- /dev/null +++ b/tests/baselines/reference/taggedTemplateContextualTyping.js @@ -0,0 +1,45 @@ +//// [taggedTemplateContextualTyping.ts] + +function tempTag1(templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; +function tempTag1(templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; +function tempTag1(...rest: any[]): T { + return undefined; +} + +tempTag1 `${ x => x }${ 10 }`; +tempTag1 `${ x => x }${ y => y }${ 10 }`; +tempTag1 `${ x => x }${ (y: number) => y }${ undefined }`; +tempTag1 `${ (x: number) => x }${ y => y }${ undefined }`; + +function tempTag2(templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; +function tempTag2(templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; +function tempTag2(...rest: any[]): any { + return undefined; +} + +tempTag2 `${ x => x }${ 0 }`; +tempTag2 `${ x => x }${ y => y }${ "hello" }`; +tempTag2 `${ x => x }${ 0 }`; + +//// [taggedTemplateContextualTyping.js] +function tempTag1() { + var rest = []; + for (var _i = 0; _i < arguments.length; _i++) { + rest[_i - 0] = arguments[_i]; + } + return undefined; +} +tempTag1 `${function (x) { return x; }}${10}`; +tempTag1 `${function (x) { return x; }}${function (y) { return y; }}${10}`; +tempTag1 `${function (x) { return x; }}${function (y) { return y; }}${undefined}`; +tempTag1 `${function (x) { return x; }}${function (y) { return y; }}${undefined}`; +function tempTag2() { + var rest = []; + for (var _i = 0; _i < arguments.length; _i++) { + rest[_i - 0] = arguments[_i]; + } + return undefined; +} +tempTag2 `${function (x) { return x; }}${0}`; +tempTag2 `${function (x) { return x; }}${function (y) { return y; }}${"hello"}`; +tempTag2 `${function (x) { return x; }}${0}`; diff --git a/tests/baselines/reference/taggedTemplateContextualTyping.types b/tests/baselines/reference/taggedTemplateContextualTyping.types new file mode 100644 index 00000000000..d8d050e4643 --- /dev/null +++ b/tests/baselines/reference/taggedTemplateContextualTyping.types @@ -0,0 +1,124 @@ +=== tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping.ts === + +function tempTag1(templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; +>tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; } +>T : T +>templateStrs : TemplateStringsArray +>TemplateStringsArray : TemplateStringsArray +>f : (x: T) => T +>x : T +>T : T +>T : T +>x : T +>T : T +>T : T + +function tempTag1(templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; +>tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; } +>T : T +>templateStrs : TemplateStringsArray +>TemplateStringsArray : TemplateStringsArray +>f : (x: T) => T +>x : T +>T : T +>T : T +>h : (y: T) => T +>y : T +>T : T +>T : T +>x : T +>T : T +>T : T + +function tempTag1(...rest: any[]): T { +>tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; } +>T : T +>rest : any[] +>T : T + + return undefined; +>undefined : undefined +} + +tempTag1 `${ x => x }${ 10 }`; +>tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; } +>x => x : (x: number) => number +>x : number +>x : number + +tempTag1 `${ x => x }${ y => y }${ 10 }`; +>tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; } +>x => x : (x: number) => number +>x : number +>x : number +>y => y : (y: number) => number +>y : number +>y : number + +tempTag1 `${ x => x }${ (y: number) => y }${ undefined }`; +>tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; } +>x => x : (x: number) => number +>x : number +>x : number +>(y: number) => y : (y: number) => number +>y : number +>y : number +>undefined : undefined + +tempTag1 `${ (x: number) => x }${ y => y }${ undefined }`; +>tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; } +>(x: number) => x : (x: number) => number +>x : number +>x : number +>y => y : (y: number) => number +>y : number +>y : number +>undefined : undefined + +function tempTag2(templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; +>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } +>templateStrs : TemplateStringsArray +>TemplateStringsArray : TemplateStringsArray +>f : (x: number) => number +>x : number +>x : number + +function tempTag2(templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; +>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } +>templateStrs : TemplateStringsArray +>TemplateStringsArray : TemplateStringsArray +>f : (x: string) => string +>x : string +>h : (y: string) => string +>y : string +>x : string + +function tempTag2(...rest: any[]): any { +>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } +>rest : any[] + + return undefined; +>undefined : undefined +} + +tempTag2 `${ x => x }${ 0 }`; +>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } +>x => x : (x: number) => number +>x : number +>x : number + +tempTag2 `${ x => x }${ y => y }${ "hello" }`; +>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } +>x => x : (x: string) => string +>x : string +>x : string +>y => y : (y: string) => string +>y : string +>y : string + +tempTag2 `${ x => x }${ 0 }`; +>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } +>x => x : (x: number) => number +>x : number +>x : number + diff --git a/tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping.ts b/tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping.ts new file mode 100644 index 00000000000..5d6137a13ac --- /dev/null +++ b/tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping.ts @@ -0,0 +1,22 @@ +// @target: ES6 + +function tempTag1(templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; +function tempTag1(templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; +function tempTag1(...rest: any[]): T { + return undefined; +} + +tempTag1 `${ x => x }${ 10 }`; +tempTag1 `${ x => x }${ y => y }${ 10 }`; +tempTag1 `${ x => x }${ (y: number) => y }${ undefined }`; +tempTag1 `${ (x: number) => x }${ y => y }${ undefined }`; + +function tempTag2(templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; +function tempTag2(templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; +function tempTag2(...rest: any[]): any { + return undefined; +} + +tempTag2 `${ x => x }${ 0 }`; +tempTag2 `${ x => x }${ y => y }${ "hello" }`; +tempTag2 `${ x => x }${ 0 }`; \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoForContextuallyTypedFunctionInTaggedTemplateExpression.ts b/tests/cases/fourslash/quickInfoForContextuallyTypedFunctionInTaggedTemplateExpression.ts new file mode 100644 index 00000000000..6d30d59ebd9 --- /dev/null +++ b/tests/cases/fourslash/quickInfoForContextuallyTypedFunctionInTaggedTemplateExpression.ts @@ -0,0 +1,44 @@ +/// + +////function tempTag1(templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; +////function tempTag1(templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; +////function tempTag1(...rest: any[]): T { +//// return undefined; +////} +//// +////tempTag1 `${ x => /*0*/x }${ 10 }`; +////tempTag1 `${ x => /*1*/x }${ x => /*2*/x }${ 10 }`; +////tempTag1 `${ x => /*3*/x }${ (x: number) => /*4*/x }${ undefined }`; +////tempTag1 `${ (x: number) => /*5*/x }${ x => /*6*/x }${ undefined }`; +//// +////function tempTag2(templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; +////function tempTag2(templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; +////function tempTag2(...rest: any[]): any { +//// return undefined; +////} +//// +////tempTag2 `${ x => /*7*/x }${ 0 }`; +////tempTag2 `${ x => /*8*/x }${ undefined }`; +////tempTag2 `${ x => /*9*/x }${ x => /*10*/x }${ "hello" }`; +////tempTag2 `${ x => /*11*/x }${ undefined }${ "hello" }`; + +// The first group of parameters, [0, 8], should all be contextually typed as 'number'. +// The second group, [9, 11], should be typed as 'string'. +var numTypedVariableCount = 9; +var strTypedVariableCount = 3; + +var markers = test.markers(); + +if (numTypedVariableCount + strTypedVariableCount !== markers.length) { + throw "Unexpected number of markers in file."; +} + +for (var i = 0; i < numTypedVariableCount; i++) { + goTo.marker("" + i); + verify.quickInfoIs("(parameter) x: number"); +} + +for (var i = 0; i < strTypedVariableCount; i++) { + goTo.marker("" + (i + numTypedVariableCount)); + verify.quickInfoIs("(parameter) x: string"); +} \ No newline at end of file From e43e5c3cde7bd6619e4c5133ea76152e2241bfb7 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 15 Dec 2014 14:13:31 -0800 Subject: [PATCH 2/7] Removed unnecessary case; substitution expressions only occur in TemplateSpans. --- src/compiler/checker.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 502b87c0c9d..dcbe7162b76 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4978,8 +4978,6 @@ module ts { return getContextualTypeForElementExpression(node); case SyntaxKind.ConditionalExpression: return getContextualTypeForConditionalOperand(node); - case SyntaxKind.TemplateExpression: - return getContextualTypeForSubstitutionExpression(parent.parent, node); case SyntaxKind.TemplateSpan: Debug.assert(parent.parent.kind === SyntaxKind.TemplateExpression); return getContextualTypeForSubstitutionExpression(parent.parent, node); From e68c53f708c69e7ea509f2240b318de03c9e7b39 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 15 Dec 2014 14:55:46 -0800 Subject: [PATCH 3/7] Separated fourslash test to two files. --- ...TypedFunctionInTaggedTemplateExpression.ts | 44 ------------------- ...ypedFunctionInTaggedTemplateExpression1.ts | 19 ++++++++ ...ypedFunctionInTaggedTemplateExpression2.ts | 31 +++++++++++++ 3 files changed, 50 insertions(+), 44 deletions(-) delete mode 100644 tests/cases/fourslash/quickInfoForContextuallyTypedFunctionInTaggedTemplateExpression.ts create mode 100644 tests/cases/fourslash/quickInfoForContextuallyTypedFunctionInTaggedTemplateExpression1.ts create mode 100644 tests/cases/fourslash/quickInfoForContextuallyTypedFunctionInTaggedTemplateExpression2.ts diff --git a/tests/cases/fourslash/quickInfoForContextuallyTypedFunctionInTaggedTemplateExpression.ts b/tests/cases/fourslash/quickInfoForContextuallyTypedFunctionInTaggedTemplateExpression.ts deleted file mode 100644 index 6d30d59ebd9..00000000000 --- a/tests/cases/fourslash/quickInfoForContextuallyTypedFunctionInTaggedTemplateExpression.ts +++ /dev/null @@ -1,44 +0,0 @@ -/// - -////function tempTag1(templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; -////function tempTag1(templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; -////function tempTag1(...rest: any[]): T { -//// return undefined; -////} -//// -////tempTag1 `${ x => /*0*/x }${ 10 }`; -////tempTag1 `${ x => /*1*/x }${ x => /*2*/x }${ 10 }`; -////tempTag1 `${ x => /*3*/x }${ (x: number) => /*4*/x }${ undefined }`; -////tempTag1 `${ (x: number) => /*5*/x }${ x => /*6*/x }${ undefined }`; -//// -////function tempTag2(templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; -////function tempTag2(templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; -////function tempTag2(...rest: any[]): any { -//// return undefined; -////} -//// -////tempTag2 `${ x => /*7*/x }${ 0 }`; -////tempTag2 `${ x => /*8*/x }${ undefined }`; -////tempTag2 `${ x => /*9*/x }${ x => /*10*/x }${ "hello" }`; -////tempTag2 `${ x => /*11*/x }${ undefined }${ "hello" }`; - -// The first group of parameters, [0, 8], should all be contextually typed as 'number'. -// The second group, [9, 11], should be typed as 'string'. -var numTypedVariableCount = 9; -var strTypedVariableCount = 3; - -var markers = test.markers(); - -if (numTypedVariableCount + strTypedVariableCount !== markers.length) { - throw "Unexpected number of markers in file."; -} - -for (var i = 0; i < numTypedVariableCount; i++) { - goTo.marker("" + i); - verify.quickInfoIs("(parameter) x: number"); -} - -for (var i = 0; i < strTypedVariableCount; i++) { - goTo.marker("" + (i + numTypedVariableCount)); - verify.quickInfoIs("(parameter) x: string"); -} \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoForContextuallyTypedFunctionInTaggedTemplateExpression1.ts b/tests/cases/fourslash/quickInfoForContextuallyTypedFunctionInTaggedTemplateExpression1.ts new file mode 100644 index 00000000000..ce6b454843a --- /dev/null +++ b/tests/cases/fourslash/quickInfoForContextuallyTypedFunctionInTaggedTemplateExpression1.ts @@ -0,0 +1,19 @@ +/// + +////function tempTag1(templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; +////function tempTag1(templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; +////function tempTag1(...rest: any[]): T { +//// return undefined; +////} +//// +////tempTag1 `${ x => /*0*/x }${ 10 }`; +////tempTag1 `${ x => /*1*/x }${ x => /*2*/x }${ 10 }`; +////tempTag1 `${ x => /*3*/x }${ (x: number) => /*4*/x }${ undefined }`; +////tempTag1 `${ (x: number) => /*5*/x }${ x => /*6*/x }${ undefined }`; + +var markers = test.markers(); + +markers.forEach(marker => { + goTo.position(marker.position); + verify.quickInfoIs("(parameter) x: number"); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoForContextuallyTypedFunctionInTaggedTemplateExpression2.ts b/tests/cases/fourslash/quickInfoForContextuallyTypedFunctionInTaggedTemplateExpression2.ts new file mode 100644 index 00000000000..d878d601416 --- /dev/null +++ b/tests/cases/fourslash/quickInfoForContextuallyTypedFunctionInTaggedTemplateExpression2.ts @@ -0,0 +1,31 @@ +/// + +////function tempTag2(templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; +////function tempTag2(templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; +////function tempTag2(...rest: any[]): any { +//// return undefined; +////} +//// +////tempTag2 `${ x => /*0*/x }${ 0 }`; +////tempTag2 `${ /*1*/x => /*2*/x }${ undefined }`; +////tempTag2 `${ x => /*3*/x }${ x => /*4*/x }${ "hello" }`; +////tempTag2 `${ x => /*5*/x }${ undefined }${ "hello" }`; + +// The first group of parameters, [0, 2], should all be contextually typed as 'number'. +// The second group, [3, 5], should be typed as 'string'. +var numTypedVariableCount = 3; +var strTypedVariableCount = 3; + +if (numTypedVariableCount + strTypedVariableCount !== test.markers().length) { + throw "Unexpected number of markers in file."; +} + +for (var i = 0; i < numTypedVariableCount; i++) { + goTo.marker("" + i); + verify.quickInfoIs("(parameter) x: number"); +} + +for (var i = 0; i < strTypedVariableCount; i++) { + goTo.marker("" + (i + numTypedVariableCount)); + verify.quickInfoIs("(parameter) x: string"); +} \ No newline at end of file From 0263d6007198ba9b4db19946cbee97197212efc3 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 15 Dec 2014 15:01:33 -0800 Subject: [PATCH 4/7] Split contextual typing test for substitution expressions into two tests. --- ....js => taggedTemplateContextualTyping1.js} | 25 ++-------- ... => taggedTemplateContextualTyping1.types} | 49 +------------------ .../taggedTemplateContextualTyping2.js | 23 +++++++++ .../taggedTemplateContextualTyping2.types | 49 +++++++++++++++++++ ....ts => taggedTemplateContextualTyping1.ts} | 10 ---- .../taggedTemplateContextualTyping2.ts | 11 +++++ 6 files changed, 87 insertions(+), 80 deletions(-) rename tests/baselines/reference/{taggedTemplateContextualTyping.js => taggedTemplateContextualTyping1.js} (51%) rename tests/baselines/reference/{taggedTemplateContextualTyping.types => taggedTemplateContextualTyping1.types} (51%) create mode 100644 tests/baselines/reference/taggedTemplateContextualTyping2.js create mode 100644 tests/baselines/reference/taggedTemplateContextualTyping2.types rename tests/cases/conformance/expressions/contextualTyping/{taggedTemplateContextualTyping.ts => taggedTemplateContextualTyping1.ts} (52%) create mode 100644 tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping2.ts diff --git a/tests/baselines/reference/taggedTemplateContextualTyping.js b/tests/baselines/reference/taggedTemplateContextualTyping1.js similarity index 51% rename from tests/baselines/reference/taggedTemplateContextualTyping.js rename to tests/baselines/reference/taggedTemplateContextualTyping1.js index 64b43031c76..1ac371a8ae4 100644 --- a/tests/baselines/reference/taggedTemplateContextualTyping.js +++ b/tests/baselines/reference/taggedTemplateContextualTyping1.js @@ -1,4 +1,4 @@ -//// [taggedTemplateContextualTyping.ts] +//// [taggedTemplateContextualTyping1.ts] function tempTag1(templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; function tempTag1(templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; @@ -10,18 +10,9 @@ tempTag1 `${ x => x }${ 10 }`; tempTag1 `${ x => x }${ y => y }${ 10 }`; tempTag1 `${ x => x }${ (y: number) => y }${ undefined }`; tempTag1 `${ (x: number) => x }${ y => y }${ undefined }`; - -function tempTag2(templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; -function tempTag2(templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; -function tempTag2(...rest: any[]): any { - return undefined; -} - -tempTag2 `${ x => x }${ 0 }`; -tempTag2 `${ x => x }${ y => y }${ "hello" }`; -tempTag2 `${ x => x }${ 0 }`; -//// [taggedTemplateContextualTyping.js] + +//// [taggedTemplateContextualTyping1.js] function tempTag1() { var rest = []; for (var _i = 0; _i < arguments.length; _i++) { @@ -33,13 +24,3 @@ tempTag1 `${function (x) { return x; }}${10}`; tempTag1 `${function (x) { return x; }}${function (y) { return y; }}${10}`; tempTag1 `${function (x) { return x; }}${function (y) { return y; }}${undefined}`; tempTag1 `${function (x) { return x; }}${function (y) { return y; }}${undefined}`; -function tempTag2() { - var rest = []; - for (var _i = 0; _i < arguments.length; _i++) { - rest[_i - 0] = arguments[_i]; - } - return undefined; -} -tempTag2 `${function (x) { return x; }}${0}`; -tempTag2 `${function (x) { return x; }}${function (y) { return y; }}${"hello"}`; -tempTag2 `${function (x) { return x; }}${0}`; diff --git a/tests/baselines/reference/taggedTemplateContextualTyping.types b/tests/baselines/reference/taggedTemplateContextualTyping1.types similarity index 51% rename from tests/baselines/reference/taggedTemplateContextualTyping.types rename to tests/baselines/reference/taggedTemplateContextualTyping1.types index d8d050e4643..bb8e6a1a87c 100644 --- a/tests/baselines/reference/taggedTemplateContextualTyping.types +++ b/tests/baselines/reference/taggedTemplateContextualTyping1.types @@ -1,4 +1,4 @@ -=== tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping.ts === +=== tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping1.ts === function tempTag1(templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; >tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; } @@ -75,50 +75,3 @@ tempTag1 `${ (x: number) => x }${ y => y }${ undefined }`; >y : number >undefined : undefined -function tempTag2(templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; ->tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } ->templateStrs : TemplateStringsArray ->TemplateStringsArray : TemplateStringsArray ->f : (x: number) => number ->x : number ->x : number - -function tempTag2(templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; ->tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } ->templateStrs : TemplateStringsArray ->TemplateStringsArray : TemplateStringsArray ->f : (x: string) => string ->x : string ->h : (y: string) => string ->y : string ->x : string - -function tempTag2(...rest: any[]): any { ->tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } ->rest : any[] - - return undefined; ->undefined : undefined -} - -tempTag2 `${ x => x }${ 0 }`; ->tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } ->x => x : (x: number) => number ->x : number ->x : number - -tempTag2 `${ x => x }${ y => y }${ "hello" }`; ->tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } ->x => x : (x: string) => string ->x : string ->x : string ->y => y : (y: string) => string ->y : string ->y : string - -tempTag2 `${ x => x }${ 0 }`; ->tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } ->x => x : (x: number) => number ->x : number ->x : number - diff --git a/tests/baselines/reference/taggedTemplateContextualTyping2.js b/tests/baselines/reference/taggedTemplateContextualTyping2.js new file mode 100644 index 00000000000..c24f5fffb59 --- /dev/null +++ b/tests/baselines/reference/taggedTemplateContextualTyping2.js @@ -0,0 +1,23 @@ +//// [taggedTemplateContextualTyping2.ts] + +function tempTag2(templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; +function tempTag2(templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; +function tempTag2(...rest: any[]): any { + return undefined; +} + +tempTag2 `${ x => x }${ 0 }`; +tempTag2 `${ x => x }${ y => y }${ "hello" }`; +tempTag2 `${ x => x }${ 0 }`; + +//// [taggedTemplateContextualTyping2.js] +function tempTag2() { + var rest = []; + for (var _i = 0; _i < arguments.length; _i++) { + rest[_i - 0] = arguments[_i]; + } + return undefined; +} +tempTag2 `${function (x) { return x; }}${0}`; +tempTag2 `${function (x) { return x; }}${function (y) { return y; }}${"hello"}`; +tempTag2 `${function (x) { return x; }}${0}`; diff --git a/tests/baselines/reference/taggedTemplateContextualTyping2.types b/tests/baselines/reference/taggedTemplateContextualTyping2.types new file mode 100644 index 00000000000..d7088735bc3 --- /dev/null +++ b/tests/baselines/reference/taggedTemplateContextualTyping2.types @@ -0,0 +1,49 @@ +=== tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping2.ts === + +function tempTag2(templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; +>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } +>templateStrs : TemplateStringsArray +>TemplateStringsArray : TemplateStringsArray +>f : (x: number) => number +>x : number +>x : number + +function tempTag2(templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; +>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } +>templateStrs : TemplateStringsArray +>TemplateStringsArray : TemplateStringsArray +>f : (x: string) => string +>x : string +>h : (y: string) => string +>y : string +>x : string + +function tempTag2(...rest: any[]): any { +>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } +>rest : any[] + + return undefined; +>undefined : undefined +} + +tempTag2 `${ x => x }${ 0 }`; +>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } +>x => x : (x: number) => number +>x : number +>x : number + +tempTag2 `${ x => x }${ y => y }${ "hello" }`; +>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } +>x => x : (x: string) => string +>x : string +>x : string +>y => y : (y: string) => string +>y : string +>y : string + +tempTag2 `${ x => x }${ 0 }`; +>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } +>x => x : (x: number) => number +>x : number +>x : number + diff --git a/tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping.ts b/tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping1.ts similarity index 52% rename from tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping.ts rename to tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping1.ts index 5d6137a13ac..1e35b3c9b4b 100644 --- a/tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping.ts +++ b/tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping1.ts @@ -10,13 +10,3 @@ tempTag1 `${ x => x }${ 10 }`; tempTag1 `${ x => x }${ y => y }${ 10 }`; tempTag1 `${ x => x }${ (y: number) => y }${ undefined }`; tempTag1 `${ (x: number) => x }${ y => y }${ undefined }`; - -function tempTag2(templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; -function tempTag2(templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; -function tempTag2(...rest: any[]): any { - return undefined; -} - -tempTag2 `${ x => x }${ 0 }`; -tempTag2 `${ x => x }${ y => y }${ "hello" }`; -tempTag2 `${ x => x }${ 0 }`; \ No newline at end of file diff --git a/tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping2.ts b/tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping2.ts new file mode 100644 index 00000000000..260a3bc0741 --- /dev/null +++ b/tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping2.ts @@ -0,0 +1,11 @@ +// @target: ES6 + +function tempTag2(templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; +function tempTag2(templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; +function tempTag2(...rest: any[]): any { + return undefined; +} + +tempTag2 `${ x => x }${ 0 }`; +tempTag2 `${ x => x }${ y => y }${ "hello" }`; +tempTag2 `${ x => x }${ 0 }`; \ No newline at end of file From 17c822966dae2f6eaa90e3f380ab6c08cdc8c2e8 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 15 Dec 2014 16:39:12 -0800 Subject: [PATCH 5/7] Added tests for erroneous function expressions in both tagged/untagged template expressions. --- ...pressionsInSubstitutionExpression.errors.txt | 12 ++++++++++++ ...ionExpressionsInSubstitutionExpressionES6.js | 17 +++++++++++++++++ ...ExpressionsInSubstitutionExpressionES6.types | 14 ++++++++++++++ ...nctionExpressionsInSubstitutionExpression.js | 9 +++++++++ ...ionExpressionsInSubstitutionExpression.types | 9 +++++++++ ...ionExpressionsInSubstitutionExpressionES6.js | 8 ++++++++ ...ExpressionsInSubstitutionExpressionES6.types | 8 ++++++++ ...nctionExpressionsInSubstitutionExpression.ts | 6 ++++++ ...ionExpressionsInSubstitutionExpressionES6.ts | 6 ++++++ ...nctionExpressionsInSubstitutionExpression.ts | 3 +++ ...ionExpressionsInSubstitutionExpressionES6.ts | 3 +++ 11 files changed, 95 insertions(+) create mode 100644 tests/baselines/reference/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.errors.txt create mode 100644 tests/baselines/reference/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.js create mode 100644 tests/baselines/reference/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.types create mode 100644 tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.js create mode 100644 tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.types create mode 100644 tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.js create mode 100644 tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.types create mode 100644 tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.ts create mode 100644 tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.ts create mode 100644 tests/cases/conformance/es6/templates/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.ts create mode 100644 tests/cases/conformance/es6/templates/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.ts diff --git a/tests/baselines/reference/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.errors.txt b/tests/baselines/reference/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.errors.txt new file mode 100644 index 00000000000..e14ffc481f5 --- /dev/null +++ b/tests/baselines/reference/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.errors.txt @@ -0,0 +1,12 @@ +tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.ts(6,5): error TS1159: Tagged templates are only available when targeting ECMAScript 6 and higher. + + +==== tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.ts (1 errors) ==== + + + function foo(...rest: any[]) { + } + + foo `${function (x: number) { x = "bad"; } }`; + ~~~ +!!! error TS1159: Tagged templates are only available when targeting ECMAScript 6 and higher. \ No newline at end of file diff --git a/tests/baselines/reference/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.js b/tests/baselines/reference/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.js new file mode 100644 index 00000000000..a1d3479f5c2 --- /dev/null +++ b/tests/baselines/reference/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.js @@ -0,0 +1,17 @@ +//// [taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.ts] + +function foo(...rest: any[]) { +} + +foo `${function (x: number) { x = "bad"; } }`; + +//// [taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.js] +function foo() { + var rest = []; + for (var _i = 0; _i < arguments.length; _i++) { + rest[_i - 0] = arguments[_i]; + } +} +foo `${function (x) { + x = "bad"; +}}`; diff --git a/tests/baselines/reference/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.types b/tests/baselines/reference/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.types new file mode 100644 index 00000000000..9d7e44f27de --- /dev/null +++ b/tests/baselines/reference/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.types @@ -0,0 +1,14 @@ +=== tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.ts === + +function foo(...rest: any[]) { +>foo : (...rest: any[]) => void +>rest : any[] +} + +foo `${function (x: number) { x = "bad"; } }`; +>foo : (...rest: any[]) => void +>function (x: number) { x = "bad"; } : (x: number) => void +>x : number +>x = "bad" : string +>x : number + diff --git a/tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.js b/tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.js new file mode 100644 index 00000000000..ef113312060 --- /dev/null +++ b/tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.js @@ -0,0 +1,9 @@ +//// [templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.ts] + + +`${function (x: number) { x = "bad"; } }`; + +//// [templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.js] +"" + function (x) { + x = "bad"; +}; diff --git a/tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.types b/tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.types new file mode 100644 index 00000000000..1afa1592ec2 --- /dev/null +++ b/tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.types @@ -0,0 +1,9 @@ +=== tests/cases/conformance/es6/templates/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.ts === + + +`${function (x: number) { x = "bad"; } }`; +>function (x: number) { x = "bad"; } : (x: number) => void +>x : number +>x = "bad" : string +>x : number + diff --git a/tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.js b/tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.js new file mode 100644 index 00000000000..9ce47348dc1 --- /dev/null +++ b/tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.js @@ -0,0 +1,8 @@ +//// [templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.ts] + +`${function (x: number) { x = "bad"; } }`; + +//// [templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.js] +`${function (x) { + x = "bad"; +}}`; diff --git a/tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.types b/tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.types new file mode 100644 index 00000000000..0a15a491413 --- /dev/null +++ b/tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.types @@ -0,0 +1,8 @@ +=== tests/cases/conformance/es6/templates/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.ts === + +`${function (x: number) { x = "bad"; } }`; +>function (x: number) { x = "bad"; } : (x: number) => void +>x : number +>x = "bad" : string +>x : number + diff --git a/tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.ts b/tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.ts new file mode 100644 index 00000000000..210f3eebbd7 --- /dev/null +++ b/tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.ts @@ -0,0 +1,6 @@ + + +function foo(...rest: any[]) { +} + +foo `${function (x: number) { x = "bad"; } }`; \ No newline at end of file diff --git a/tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.ts b/tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.ts new file mode 100644 index 00000000000..0a51fea491f --- /dev/null +++ b/tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.ts @@ -0,0 +1,6 @@ +//@target: es6 + +function foo(...rest: any[]) { +} + +foo `${function (x: number) { x = "bad"; } }`; \ No newline at end of file diff --git a/tests/cases/conformance/es6/templates/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.ts b/tests/cases/conformance/es6/templates/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.ts new file mode 100644 index 00000000000..26995f21e58 --- /dev/null +++ b/tests/cases/conformance/es6/templates/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.ts @@ -0,0 +1,3 @@ + + +`${function (x: number) { x = "bad"; } }`; \ No newline at end of file diff --git a/tests/cases/conformance/es6/templates/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.ts b/tests/cases/conformance/es6/templates/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.ts new file mode 100644 index 00000000000..4803285a24a --- /dev/null +++ b/tests/cases/conformance/es6/templates/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.ts @@ -0,0 +1,3 @@ +//@target: es6 + +`${function (x: number) { x = "bad"; } }`; \ No newline at end of file From e3848b98b1717d7170e419d5b28c5babfc041826 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 15 Dec 2014 16:45:17 -0800 Subject: [PATCH 6/7] Fixed bug where function expressions were not getting checked in template expressions. --- src/compiler/checker.ts | 2 ++ ...nExpressionsInSubstitutionExpression.errors.txt | 7 +++++-- ...pressionsInSubstitutionExpressionES6.errors.txt | 11 +++++++++++ ...ionExpressionsInSubstitutionExpressionES6.types | 14 -------------- ...nExpressionsInSubstitutionExpression.errors.txt | 9 +++++++++ ...nctionExpressionsInSubstitutionExpression.types | 9 --------- ...pressionsInSubstitutionExpressionES6.errors.txt | 8 ++++++++ ...ionExpressionsInSubstitutionExpressionES6.types | 8 -------- 8 files changed, 35 insertions(+), 33 deletions(-) create mode 100644 tests/baselines/reference/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.errors.txt delete mode 100644 tests/baselines/reference/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.types create mode 100644 tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.errors.txt delete mode 100644 tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.types create mode 100644 tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.errors.txt delete mode 100644 tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.types diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index dcbe7162b76..b0c0305670e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8647,6 +8647,8 @@ module ts { case SyntaxKind.CallExpression: case SyntaxKind.NewExpression: case SyntaxKind.TaggedTemplateExpression: + case SyntaxKind.TemplateExpression: + case SyntaxKind.TemplateSpan: case SyntaxKind.TypeAssertionExpression: case SyntaxKind.ParenthesizedExpression: case SyntaxKind.TypeOfExpression: diff --git a/tests/baselines/reference/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.errors.txt b/tests/baselines/reference/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.errors.txt index e14ffc481f5..b38a70ca18b 100644 --- a/tests/baselines/reference/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.errors.txt +++ b/tests/baselines/reference/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.errors.txt @@ -1,7 +1,8 @@ tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.ts(6,5): error TS1159: Tagged templates are only available when targeting ECMAScript 6 and higher. +tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.ts(6,31): error TS2322: Type 'string' is not assignable to type 'number'. -==== tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.ts (1 errors) ==== +==== tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.ts (2 errors) ==== function foo(...rest: any[]) { @@ -9,4 +10,6 @@ tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypeErrorInFuncti foo `${function (x: number) { x = "bad"; } }`; ~~~ -!!! error TS1159: Tagged templates are only available when targeting ECMAScript 6 and higher. \ No newline at end of file +!!! error TS1159: Tagged templates are only available when targeting ECMAScript 6 and higher. + ~ +!!! error TS2322: Type 'string' is not assignable to type 'number'. \ No newline at end of file diff --git a/tests/baselines/reference/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.errors.txt b/tests/baselines/reference/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.errors.txt new file mode 100644 index 00000000000..6b0f4b642ff --- /dev/null +++ b/tests/baselines/reference/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.errors.txt @@ -0,0 +1,11 @@ +tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.ts(5,31): error TS2322: Type 'string' is not assignable to type 'number'. + + +==== tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.ts (1 errors) ==== + + function foo(...rest: any[]) { + } + + foo `${function (x: number) { x = "bad"; } }`; + ~ +!!! error TS2322: Type 'string' is not assignable to type 'number'. \ No newline at end of file diff --git a/tests/baselines/reference/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.types b/tests/baselines/reference/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.types deleted file mode 100644 index 9d7e44f27de..00000000000 --- a/tests/baselines/reference/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.types +++ /dev/null @@ -1,14 +0,0 @@ -=== tests/cases/conformance/es6/templates/taggedTemplateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.ts === - -function foo(...rest: any[]) { ->foo : (...rest: any[]) => void ->rest : any[] -} - -foo `${function (x: number) { x = "bad"; } }`; ->foo : (...rest: any[]) => void ->function (x: number) { x = "bad"; } : (x: number) => void ->x : number ->x = "bad" : string ->x : number - diff --git a/tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.errors.txt b/tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.errors.txt new file mode 100644 index 00000000000..7204f32dba2 --- /dev/null +++ b/tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.errors.txt @@ -0,0 +1,9 @@ +tests/cases/conformance/es6/templates/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.ts(3,27): error TS2322: Type 'string' is not assignable to type 'number'. + + +==== tests/cases/conformance/es6/templates/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.ts (1 errors) ==== + + + `${function (x: number) { x = "bad"; } }`; + ~ +!!! error TS2322: Type 'string' is not assignable to type 'number'. \ No newline at end of file diff --git a/tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.types b/tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.types deleted file mode 100644 index 1afa1592ec2..00000000000 --- a/tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.types +++ /dev/null @@ -1,9 +0,0 @@ -=== tests/cases/conformance/es6/templates/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.ts === - - -`${function (x: number) { x = "bad"; } }`; ->function (x: number) { x = "bad"; } : (x: number) => void ->x : number ->x = "bad" : string ->x : number - diff --git a/tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.errors.txt b/tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.errors.txt new file mode 100644 index 00000000000..9fece57ef5e --- /dev/null +++ b/tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.errors.txt @@ -0,0 +1,8 @@ +tests/cases/conformance/es6/templates/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.ts(2,27): error TS2322: Type 'string' is not assignable to type 'number'. + + +==== tests/cases/conformance/es6/templates/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.ts (1 errors) ==== + + `${function (x: number) { x = "bad"; } }`; + ~ +!!! error TS2322: Type 'string' is not assignable to type 'number'. \ No newline at end of file diff --git a/tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.types b/tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.types deleted file mode 100644 index 0a15a491413..00000000000 --- a/tests/baselines/reference/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.types +++ /dev/null @@ -1,8 +0,0 @@ -=== tests/cases/conformance/es6/templates/templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.ts === - -`${function (x: number) { x = "bad"; } }`; ->function (x: number) { x = "bad"; } : (x: number) => void ->x : number ->x = "bad" : string ->x : number - From 1f6cd941fdaa37c25da86eb86601b46037773e35 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 15 Dec 2014 17:09:56 -0800 Subject: [PATCH 7/7] Changed tests to error when actual contextual typing is broken. --- .../taggedTemplateContextualTyping1.js | 46 +++++-- .../taggedTemplateContextualTyping1.types | 121 +++++++++++------- .../taggedTemplateContextualTyping2.js | 39 ++++-- .../taggedTemplateContextualTyping2.types | 93 +++++++++----- .../taggedTemplateContextualTyping1.ts | 17 ++- .../taggedTemplateContextualTyping2.ts | 17 ++- 6 files changed, 228 insertions(+), 105 deletions(-) diff --git a/tests/baselines/reference/taggedTemplateContextualTyping1.js b/tests/baselines/reference/taggedTemplateContextualTyping1.js index 1ac371a8ae4..1d8b79e4c32 100644 --- a/tests/baselines/reference/taggedTemplateContextualTyping1.js +++ b/tests/baselines/reference/taggedTemplateContextualTyping1.js @@ -1,15 +1,20 @@ //// [taggedTemplateContextualTyping1.ts] -function tempTag1(templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; -function tempTag1(templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; +type FuncType = (x: (p: T) => T) => typeof x; + +function tempTag1(templateStrs: TemplateStringsArray, f: FuncType, x: T): T; +function tempTag1(templateStrs: TemplateStringsArray, f: FuncType, h: FuncType, x: T): T; function tempTag1(...rest: any[]): T { return undefined; } -tempTag1 `${ x => x }${ 10 }`; -tempTag1 `${ x => x }${ y => y }${ 10 }`; -tempTag1 `${ x => x }${ (y: number) => y }${ undefined }`; -tempTag1 `${ (x: number) => x }${ y => y }${ undefined }`; +// If contextual typing takes place, these functions should work. +// Otherwise, the arrow functions' parameters will be typed as 'any', +// and it is an error to invoke an any-typed value with type arguments, +// so this test will error. +tempTag1 `${ x => { x(undefined); return x; } }${ y => { y(undefined); return y; } }${ 10 }`; +tempTag1 `${ x => { x(undefined); return x; } }${ (y: (p: T) => T) => { y(undefined); return y } }${ undefined }`; +tempTag1 `${ (x: (p: T) => T) => { x(undefined); return x; } }${ y => { y(undefined); return y; } }${ undefined }`; //// [taggedTemplateContextualTyping1.js] @@ -20,7 +25,28 @@ function tempTag1() { } return undefined; } -tempTag1 `${function (x) { return x; }}${10}`; -tempTag1 `${function (x) { return x; }}${function (y) { return y; }}${10}`; -tempTag1 `${function (x) { return x; }}${function (y) { return y; }}${undefined}`; -tempTag1 `${function (x) { return x; }}${function (y) { return y; }}${undefined}`; +// If contextual typing takes place, these functions should work. +// Otherwise, the arrow functions' parameters will be typed as 'any', +// and it is an error to invoke an any-typed value with type arguments, +// so this test will error. +tempTag1 `${function (x) { + x(undefined); + return x; +}}${function (y) { + y(undefined); + return y; +}}${10}`; +tempTag1 `${function (x) { + x(undefined); + return x; +}}${function (y) { + y(undefined); + return y; +}}${undefined}`; +tempTag1 `${function (x) { + x(undefined); + return x; +}}${function (y) { + y(undefined); + return y; +}}${undefined}`; diff --git a/tests/baselines/reference/taggedTemplateContextualTyping1.types b/tests/baselines/reference/taggedTemplateContextualTyping1.types index bb8e6a1a87c..a87d5eaa7a4 100644 --- a/tests/baselines/reference/taggedTemplateContextualTyping1.types +++ b/tests/baselines/reference/taggedTemplateContextualTyping1.types @@ -1,37 +1,40 @@ === tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping1.ts === -function tempTag1(templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; ->tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; } +type FuncType = (x: (p: T) => T) => typeof x; +>FuncType : (x: (p: T) => T) => (p: T) => T +>x : (p: T) => T +>T : T +>p : T +>T : T +>T : T +>x : (p: T) => T + +function tempTag1(templateStrs: TemplateStringsArray, f: FuncType, x: T): T; +>tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, h: (x: (p: T) => T) => (p: T) => T, x: T): T; } >T : T >templateStrs : TemplateStringsArray >TemplateStringsArray : TemplateStringsArray ->f : (x: T) => T ->x : T ->T : T ->T : T +>f : (x: (p: T) => T) => (p: T) => T +>FuncType : (x: (p: T) => T) => (p: T) => T >x : T >T : T >T : T -function tempTag1(templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; ->tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; } +function tempTag1(templateStrs: TemplateStringsArray, f: FuncType, h: FuncType, x: T): T; +>tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, h: (x: (p: T) => T) => (p: T) => T, x: T): T; } >T : T >templateStrs : TemplateStringsArray >TemplateStringsArray : TemplateStringsArray ->f : (x: T) => T ->x : T ->T : T ->T : T ->h : (y: T) => T ->y : T ->T : T ->T : T +>f : (x: (p: T) => T) => (p: T) => T +>FuncType : (x: (p: T) => T) => (p: T) => T +>h : (x: (p: T) => T) => (p: T) => T +>FuncType : (x: (p: T) => T) => (p: T) => T >x : T >T : T >T : T function tempTag1(...rest: any[]): T { ->tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; } +>tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, h: (x: (p: T) => T) => (p: T) => T, x: T): T; } >T : T >rest : any[] >T : T @@ -40,38 +43,62 @@ function tempTag1(...rest: any[]): T { >undefined : undefined } -tempTag1 `${ x => x }${ 10 }`; ->tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; } ->x => x : (x: number) => number ->x : number ->x : number +// If contextual typing takes place, these functions should work. +// Otherwise, the arrow functions' parameters will be typed as 'any', +// and it is an error to invoke an any-typed value with type arguments, +// so this test will error. +tempTag1 `${ x => { x(undefined); return x; } }${ y => { y(undefined); return y; } }${ 10 }`; +>tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, h: (x: (p: T) => T) => (p: T) => T, x: T): T; } +>x => { x(undefined); return x; } : (x: (p: T) => T) => (p: T) => T +>x : (p: T) => T +>x(undefined) : number +>x : (p: T) => T +>undefined : undefined +>x : (p: T) => T +>y => { y(undefined); return y; } : (y: (p: T) => T) => (p: T) => T +>y : (p: T) => T +>y(undefined) : number +>y : (p: T) => T +>undefined : undefined +>y : (p: T) => T -tempTag1 `${ x => x }${ y => y }${ 10 }`; ->tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; } ->x => x : (x: number) => number ->x : number ->x : number ->y => y : (y: number) => number ->y : number ->y : number - -tempTag1 `${ x => x }${ (y: number) => y }${ undefined }`; ->tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; } ->x => x : (x: number) => number ->x : number ->x : number ->(y: number) => y : (y: number) => number ->y : number ->y : number +tempTag1 `${ x => { x(undefined); return x; } }${ (y: (p: T) => T) => { y(undefined); return y } }${ undefined }`; +>tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, h: (x: (p: T) => T) => (p: T) => T, x: T): T; } +>x => { x(undefined); return x; } : (x: (p: T) => T) => (p: T) => T +>x : (p: T) => T +>x(undefined) : number +>x : (p: T) => T +>undefined : undefined +>x : (p: T) => T +>(y: (p: T) => T) => { y(undefined); return y } : (y: (p: T) => T) => (p: T) => T +>y : (p: T) => T +>T : T +>p : T +>T : T +>T : T +>y(undefined) : number +>y : (p: T) => T +>undefined : undefined +>y : (p: T) => T >undefined : undefined -tempTag1 `${ (x: number) => x }${ y => y }${ undefined }`; ->tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; } ->(x: number) => x : (x: number) => number ->x : number ->x : number ->y => y : (y: number) => number ->y : number ->y : number +tempTag1 `${ (x: (p: T) => T) => { x(undefined); return x; } }${ y => { y(undefined); return y; } }${ undefined }`; +>tempTag1 : { (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, x: T): T; (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, h: (x: (p: T) => T) => (p: T) => T, x: T): T; } +>(x: (p: T) => T) => { x(undefined); return x; } : (x: (p: T) => T) => (p: T) => T +>x : (p: T) => T +>T : T +>p : T +>T : T +>T : T +>x(undefined) : number +>x : (p: T) => T +>undefined : undefined +>x : (p: T) => T +>y => { y(undefined); return y; } : (y: (p: T) => T) => (p: T) => T +>y : (p: T) => T +>y(undefined) : number +>y : (p: T) => T +>undefined : undefined +>y : (p: T) => T >undefined : undefined diff --git a/tests/baselines/reference/taggedTemplateContextualTyping2.js b/tests/baselines/reference/taggedTemplateContextualTyping2.js index c24f5fffb59..df026399c10 100644 --- a/tests/baselines/reference/taggedTemplateContextualTyping2.js +++ b/tests/baselines/reference/taggedTemplateContextualTyping2.js @@ -1,14 +1,21 @@ //// [taggedTemplateContextualTyping2.ts] -function tempTag2(templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; -function tempTag2(templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; +type FuncType1 = (x: (p: T) => T) => typeof x; +type FuncType2 = (x: (p: T) => T) => typeof x; + +function tempTag2(templateStrs: TemplateStringsArray, f: FuncType1, x: number): number; +function tempTag2(templateStrs: TemplateStringsArray, f: FuncType2, h: FuncType2, x: string): string; function tempTag2(...rest: any[]): any { return undefined; } -tempTag2 `${ x => x }${ 0 }`; -tempTag2 `${ x => x }${ y => y }${ "hello" }`; -tempTag2 `${ x => x }${ 0 }`; +// If contextual typing takes place, these functions should work. +// Otherwise, the arrow functions' parameters will be typed as 'any', +// and it is an error to invoke an any-typed value with type arguments, +// so this test will error. +tempTag2 `${ x => { x(undefined); return x; } }${ 0 }`; +tempTag2 `${ x => { x(undefined); return x; } }${ y => { y(null); return y; } }${ "hello" }`; +tempTag2 `${ x => { x(undefined); return x; } }${ undefined }${ "hello" }`; //// [taggedTemplateContextualTyping2.js] function tempTag2() { @@ -18,6 +25,22 @@ function tempTag2() { } return undefined; } -tempTag2 `${function (x) { return x; }}${0}`; -tempTag2 `${function (x) { return x; }}${function (y) { return y; }}${"hello"}`; -tempTag2 `${function (x) { return x; }}${0}`; +// If contextual typing takes place, these functions should work. +// Otherwise, the arrow functions' parameters will be typed as 'any', +// and it is an error to invoke an any-typed value with type arguments, +// so this test will error. +tempTag2 `${function (x) { + x(undefined); + return x; +}}${0}`; +tempTag2 `${function (x) { + x(undefined); + return x; +}}${function (y) { + y(null); + return y; +}}${"hello"}`; +tempTag2 `${function (x) { + x(undefined); + return x; +}}${undefined}${"hello"}`; diff --git a/tests/baselines/reference/taggedTemplateContextualTyping2.types b/tests/baselines/reference/taggedTemplateContextualTyping2.types index d7088735bc3..9ca7386dc34 100644 --- a/tests/baselines/reference/taggedTemplateContextualTyping2.types +++ b/tests/baselines/reference/taggedTemplateContextualTyping2.types @@ -1,49 +1,84 @@ === tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping2.ts === -function tempTag2(templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; ->tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } +type FuncType1 = (x: (p: T) => T) => typeof x; +>FuncType1 : (x: (p: T) => T) => (p: T) => T +>x : (p: T) => T +>T : T +>p : T +>T : T +>T : T +>x : (p: T) => T + +type FuncType2 = (x: (p: T) => T) => typeof x; +>FuncType2 : (x: (p: T) => T) => (p: T) => T +>x : (p: T) => T +>S : S +>T : T +>p : T +>T : T +>T : T +>x : (p: T) => T + +function tempTag2(templateStrs: TemplateStringsArray, f: FuncType1, x: number): number; +>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, x: number): number; (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, h: (x: (p: T) => T) => (p: T) => T, x: string): string; } >templateStrs : TemplateStringsArray >TemplateStringsArray : TemplateStringsArray ->f : (x: number) => number ->x : number +>f : (x: (p: T) => T) => (p: T) => T +>FuncType1 : (x: (p: T) => T) => (p: T) => T >x : number -function tempTag2(templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; ->tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } +function tempTag2(templateStrs: TemplateStringsArray, f: FuncType2, h: FuncType2, x: string): string; +>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, x: number): number; (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, h: (x: (p: T) => T) => (p: T) => T, x: string): string; } >templateStrs : TemplateStringsArray >TemplateStringsArray : TemplateStringsArray ->f : (x: string) => string ->x : string ->h : (y: string) => string ->y : string +>f : (x: (p: T) => T) => (p: T) => T +>FuncType2 : (x: (p: T) => T) => (p: T) => T +>h : (x: (p: T) => T) => (p: T) => T +>FuncType2 : (x: (p: T) => T) => (p: T) => T >x : string function tempTag2(...rest: any[]): any { ->tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } +>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, x: number): number; (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, h: (x: (p: T) => T) => (p: T) => T, x: string): string; } >rest : any[] return undefined; >undefined : undefined } -tempTag2 `${ x => x }${ 0 }`; ->tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } ->x => x : (x: number) => number ->x : number ->x : number +// If contextual typing takes place, these functions should work. +// Otherwise, the arrow functions' parameters will be typed as 'any', +// and it is an error to invoke an any-typed value with type arguments, +// so this test will error. +tempTag2 `${ x => { x(undefined); return x; } }${ 0 }`; +>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, x: number): number; (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, h: (x: (p: T) => T) => (p: T) => T, x: string): string; } +>x => { x(undefined); return x; } : (x: (p: T) => T) => (p: T) => T +>x : (p: T) => T +>x(undefined) : number +>x : (p: T) => T +>undefined : undefined +>x : (p: T) => T -tempTag2 `${ x => x }${ y => y }${ "hello" }`; ->tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } ->x => x : (x: string) => string ->x : string ->x : string ->y => y : (y: string) => string ->y : string ->y : string +tempTag2 `${ x => { x(undefined); return x; } }${ y => { y(null); return y; } }${ "hello" }`; +>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, x: number): number; (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, h: (x: (p: T) => T) => (p: T) => T, x: string): string; } +>x => { x(undefined); return x; } : (x: (p: T) => T) => (p: T) => T +>x : (p: T) => T +>x(undefined) : string +>x : (p: T) => T +>undefined : undefined +>x : (p: T) => T +>y => { y(null); return y; } : (y: (p: T) => T) => (p: T) => T +>y : (p: T) => T +>y(null) : number +>y : (p: T) => T +>y : (p: T) => T -tempTag2 `${ x => x }${ 0 }`; ->tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; (templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; } ->x => x : (x: number) => number ->x : number ->x : number +tempTag2 `${ x => { x(undefined); return x; } }${ undefined }${ "hello" }`; +>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, x: number): number; (templateStrs: TemplateStringsArray, f: (x: (p: T) => T) => (p: T) => T, h: (x: (p: T) => T) => (p: T) => T, x: string): string; } +>x => { x(undefined); return x; } : (x: (p: T) => T) => (p: T) => T +>x : (p: T) => T +>x(undefined) : string +>x : (p: T) => T +>undefined : undefined +>x : (p: T) => T +>undefined : undefined diff --git a/tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping1.ts b/tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping1.ts index 1e35b3c9b4b..c15d911ee52 100644 --- a/tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping1.ts +++ b/tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping1.ts @@ -1,12 +1,17 @@ // @target: ES6 -function tempTag1(templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T; -function tempTag1(templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T; +type FuncType = (x: (p: T) => T) => typeof x; + +function tempTag1(templateStrs: TemplateStringsArray, f: FuncType, x: T): T; +function tempTag1(templateStrs: TemplateStringsArray, f: FuncType, h: FuncType, x: T): T; function tempTag1(...rest: any[]): T { return undefined; } -tempTag1 `${ x => x }${ 10 }`; -tempTag1 `${ x => x }${ y => y }${ 10 }`; -tempTag1 `${ x => x }${ (y: number) => y }${ undefined }`; -tempTag1 `${ (x: number) => x }${ y => y }${ undefined }`; +// If contextual typing takes place, these functions should work. +// Otherwise, the arrow functions' parameters will be typed as 'any', +// and it is an error to invoke an any-typed value with type arguments, +// so this test will error. +tempTag1 `${ x => { x(undefined); return x; } }${ y => { y(undefined); return y; } }${ 10 }`; +tempTag1 `${ x => { x(undefined); return x; } }${ (y: (p: T) => T) => { y(undefined); return y } }${ undefined }`; +tempTag1 `${ (x: (p: T) => T) => { x(undefined); return x; } }${ y => { y(undefined); return y; } }${ undefined }`; diff --git a/tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping2.ts b/tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping2.ts index 260a3bc0741..24fcf4a04df 100644 --- a/tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping2.ts +++ b/tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping2.ts @@ -1,11 +1,18 @@ // @target: ES6 -function tempTag2(templateStrs: TemplateStringsArray, f: (x: number) => number, x: number): number; -function tempTag2(templateStrs: TemplateStringsArray, f: (x: string) => string, h: (y: string) => string, x: string): string; +type FuncType1 = (x: (p: T) => T) => typeof x; +type FuncType2 = (x: (p: T) => T) => typeof x; + +function tempTag2(templateStrs: TemplateStringsArray, f: FuncType1, x: number): number; +function tempTag2(templateStrs: TemplateStringsArray, f: FuncType2, h: FuncType2, x: string): string; function tempTag2(...rest: any[]): any { return undefined; } -tempTag2 `${ x => x }${ 0 }`; -tempTag2 `${ x => x }${ y => y }${ "hello" }`; -tempTag2 `${ x => x }${ 0 }`; \ No newline at end of file +// If contextual typing takes place, these functions should work. +// Otherwise, the arrow functions' parameters will be typed as 'any', +// and it is an error to invoke an any-typed value with type arguments, +// so this test will error. +tempTag2 `${ x => { x(undefined); return x; } }${ 0 }`; +tempTag2 `${ x => { x(undefined); return x; } }${ y => { y(null); return y; } }${ "hello" }`; +tempTag2 `${ x => { x(undefined); return x; } }${ undefined }${ "hello" }`; \ No newline at end of file