Merge pull request #1492 from Microsoft/contextualTemplateTyping

Fixed contextual type resolution and type checking for tagged template expressions.
This commit is contained in:
Daniel Rosenwasser
2014-12-16 00:04:45 -08:00
20 changed files with 486 additions and 7 deletions
+20 -7
View File
@@ -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 = <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(<TaggedTemplateExpression>template.parent, substitutionExpression);
}
return undefined;
}
function getContextualTypeForBinaryOperand(node: Expression): Type {
var binaryExpression = <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(<CallExpression>parent, node);
case SyntaxKind.TypeAssertionExpression:
return getTypeFromTypeNode((<TypeAssertion>parent).type);
case SyntaxKind.BinaryExpression:
@@ -4970,6 +4978,9 @@ module ts {
return getContextualTypeForElementExpression(node);
case SyntaxKind.ConditionalExpression:
return getContextualTypeForConditionalOperand(node);
case SyntaxKind.TemplateSpan:
Debug.assert(parent.parent.kind === SyntaxKind.TemplateExpression);
return getContextualTypeForSubstitutionExpression(<TemplateExpression>parent.parent, node);
}
return undefined;
}
@@ -5571,7 +5582,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
@@ -8636,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:
@@ -0,0 +1,52 @@
//// [taggedTemplateContextualTyping1.ts]
type FuncType = (x: <T>(p: T) => T) => typeof x;
function tempTag1<T>(templateStrs: TemplateStringsArray, f: FuncType, x: T): T;
function tempTag1<T>(templateStrs: TemplateStringsArray, f: FuncType, h: FuncType, x: T): T;
function tempTag1<T>(...rest: any[]): T {
return 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<number>(undefined); return x; } }${ y => { y<number>(undefined); return y; } }${ 10 }`;
tempTag1 `${ x => { x<number>(undefined); return x; } }${ (y: <T>(p: T) => T) => { y<number>(undefined); return y } }${ undefined }`;
tempTag1 `${ (x: <T>(p: T) => T) => { x<number>(undefined); return x; } }${ y => { y<number>(undefined); return y; } }${ undefined }`;
//// [taggedTemplateContextualTyping1.js]
function tempTag1() {
var rest = [];
for (var _i = 0; _i < arguments.length; _i++) {
rest[_i - 0] = arguments[_i];
}
return 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}`;
@@ -0,0 +1,104 @@
=== tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping1.ts ===
type FuncType = (x: <T>(p: T) => T) => typeof x;
>FuncType : (x: <T>(p: T) => T) => <T>(p: T) => T
>x : <T>(p: T) => T
>T : T
>p : T
>T : T
>T : T
>x : <T>(p: T) => T
function tempTag1<T>(templateStrs: TemplateStringsArray, f: FuncType, x: T): T;
>tempTag1 : { <T>(templateStrs: TemplateStringsArray, f: (x: <T>(p: T) => T) => <T>(p: T) => T, x: T): T; <T>(templateStrs: TemplateStringsArray, f: (x: <T>(p: T) => T) => <T>(p: T) => T, h: (x: <T>(p: T) => T) => <T>(p: T) => T, x: T): T; }
>T : T
>templateStrs : TemplateStringsArray
>TemplateStringsArray : TemplateStringsArray
>f : (x: <T>(p: T) => T) => <T>(p: T) => T
>FuncType : (x: <T>(p: T) => T) => <T>(p: T) => T
>x : T
>T : T
>T : T
function tempTag1<T>(templateStrs: TemplateStringsArray, f: FuncType, h: FuncType, x: T): T;
>tempTag1 : { <T>(templateStrs: TemplateStringsArray, f: (x: <T>(p: T) => T) => <T>(p: T) => T, x: T): T; <T>(templateStrs: TemplateStringsArray, f: (x: <T>(p: T) => T) => <T>(p: T) => T, h: (x: <T>(p: T) => T) => <T>(p: T) => T, x: T): T; }
>T : T
>templateStrs : TemplateStringsArray
>TemplateStringsArray : TemplateStringsArray
>f : (x: <T>(p: T) => T) => <T>(p: T) => T
>FuncType : (x: <T>(p: T) => T) => <T>(p: T) => T
>h : (x: <T>(p: T) => T) => <T>(p: T) => T
>FuncType : (x: <T>(p: T) => T) => <T>(p: T) => T
>x : T
>T : T
>T : T
function tempTag1<T>(...rest: any[]): T {
>tempTag1 : { <T>(templateStrs: TemplateStringsArray, f: (x: <T>(p: T) => T) => <T>(p: T) => T, x: T): T; <T>(templateStrs: TemplateStringsArray, f: (x: <T>(p: T) => T) => <T>(p: T) => T, h: (x: <T>(p: T) => T) => <T>(p: T) => T, x: T): T; }
>T : T
>rest : any[]
>T : T
return undefined;
>undefined : 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<number>(undefined); return x; } }${ y => { y<number>(undefined); return y; } }${ 10 }`;
>tempTag1 : { <T>(templateStrs: TemplateStringsArray, f: (x: <T>(p: T) => T) => <T>(p: T) => T, x: T): T; <T>(templateStrs: TemplateStringsArray, f: (x: <T>(p: T) => T) => <T>(p: T) => T, h: (x: <T>(p: T) => T) => <T>(p: T) => T, x: T): T; }
>x => { x<number>(undefined); return x; } : (x: <T>(p: T) => T) => <T>(p: T) => T
>x : <T>(p: T) => T
>x<number>(undefined) : number
>x : <T>(p: T) => T
>undefined : undefined
>x : <T>(p: T) => T
>y => { y<number>(undefined); return y; } : (y: <T>(p: T) => T) => <T>(p: T) => T
>y : <T>(p: T) => T
>y<number>(undefined) : number
>y : <T>(p: T) => T
>undefined : undefined
>y : <T>(p: T) => T
tempTag1 `${ x => { x<number>(undefined); return x; } }${ (y: <T>(p: T) => T) => { y<number>(undefined); return y } }${ undefined }`;
>tempTag1 : { <T>(templateStrs: TemplateStringsArray, f: (x: <T>(p: T) => T) => <T>(p: T) => T, x: T): T; <T>(templateStrs: TemplateStringsArray, f: (x: <T>(p: T) => T) => <T>(p: T) => T, h: (x: <T>(p: T) => T) => <T>(p: T) => T, x: T): T; }
>x => { x<number>(undefined); return x; } : (x: <T>(p: T) => T) => <T>(p: T) => T
>x : <T>(p: T) => T
>x<number>(undefined) : number
>x : <T>(p: T) => T
>undefined : undefined
>x : <T>(p: T) => T
>(y: <T>(p: T) => T) => { y<number>(undefined); return y } : (y: <T>(p: T) => T) => <T>(p: T) => T
>y : <T>(p: T) => T
>T : T
>p : T
>T : T
>T : T
>y<number>(undefined) : number
>y : <T>(p: T) => T
>undefined : undefined
>y : <T>(p: T) => T
>undefined : undefined
tempTag1 `${ (x: <T>(p: T) => T) => { x<number>(undefined); return x; } }${ y => { y<number>(undefined); return y; } }${ undefined }`;
>tempTag1 : { <T>(templateStrs: TemplateStringsArray, f: (x: <T>(p: T) => T) => <T>(p: T) => T, x: T): T; <T>(templateStrs: TemplateStringsArray, f: (x: <T>(p: T) => T) => <T>(p: T) => T, h: (x: <T>(p: T) => T) => <T>(p: T) => T, x: T): T; }
>(x: <T>(p: T) => T) => { x<number>(undefined); return x; } : (x: <T>(p: T) => T) => <T>(p: T) => T
>x : <T>(p: T) => T
>T : T
>p : T
>T : T
>T : T
>x<number>(undefined) : number
>x : <T>(p: T) => T
>undefined : undefined
>x : <T>(p: T) => T
>y => { y<number>(undefined); return y; } : (y: <T>(p: T) => T) => <T>(p: T) => T
>y : <T>(p: T) => T
>y<number>(undefined) : number
>y : <T>(p: T) => T
>undefined : undefined
>y : <T>(p: T) => T
>undefined : undefined
@@ -0,0 +1,46 @@
//// [taggedTemplateContextualTyping2.ts]
type FuncType1 = (x: <T>(p: T) => T) => typeof x;
type FuncType2 = (x: <S, T>(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;
}
// 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<number>(undefined); return x; } }${ 0 }`;
tempTag2 `${ x => { x<number, string>(undefined); return x; } }${ y => { y<string, number>(null); return y; } }${ "hello" }`;
tempTag2 `${ x => { x<number, string>(undefined); return x; } }${ undefined }${ "hello" }`;
//// [taggedTemplateContextualTyping2.js]
function tempTag2() {
var rest = [];
for (var _i = 0; _i < arguments.length; _i++) {
rest[_i - 0] = arguments[_i];
}
return 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.
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"}`;
@@ -0,0 +1,84 @@
=== tests/cases/conformance/expressions/contextualTyping/taggedTemplateContextualTyping2.ts ===
type FuncType1 = (x: <T>(p: T) => T) => typeof x;
>FuncType1 : (x: <T>(p: T) => T) => <T>(p: T) => T
>x : <T>(p: T) => T
>T : T
>p : T
>T : T
>T : T
>x : <T>(p: T) => T
type FuncType2 = (x: <S, T>(p: T) => T) => typeof x;
>FuncType2 : (x: <S, T>(p: T) => T) => <S, T>(p: T) => T
>x : <S, T>(p: T) => T
>S : S
>T : T
>p : T
>T : T
>T : T
>x : <S, T>(p: T) => T
function tempTag2(templateStrs: TemplateStringsArray, f: FuncType1, x: number): number;
>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: <T>(p: T) => T) => <T>(p: T) => T, x: number): number; (templateStrs: TemplateStringsArray, f: (x: <S, T>(p: T) => T) => <S, T>(p: T) => T, h: (x: <S, T>(p: T) => T) => <S, T>(p: T) => T, x: string): string; }
>templateStrs : TemplateStringsArray
>TemplateStringsArray : TemplateStringsArray
>f : (x: <T>(p: T) => T) => <T>(p: T) => T
>FuncType1 : (x: <T>(p: T) => T) => <T>(p: T) => T
>x : number
function tempTag2(templateStrs: TemplateStringsArray, f: FuncType2, h: FuncType2, x: string): string;
>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: <T>(p: T) => T) => <T>(p: T) => T, x: number): number; (templateStrs: TemplateStringsArray, f: (x: <S, T>(p: T) => T) => <S, T>(p: T) => T, h: (x: <S, T>(p: T) => T) => <S, T>(p: T) => T, x: string): string; }
>templateStrs : TemplateStringsArray
>TemplateStringsArray : TemplateStringsArray
>f : (x: <S, T>(p: T) => T) => <S, T>(p: T) => T
>FuncType2 : (x: <S, T>(p: T) => T) => <S, T>(p: T) => T
>h : (x: <S, T>(p: T) => T) => <S, T>(p: T) => T
>FuncType2 : (x: <S, T>(p: T) => T) => <S, T>(p: T) => T
>x : string
function tempTag2(...rest: any[]): any {
>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: <T>(p: T) => T) => <T>(p: T) => T, x: number): number; (templateStrs: TemplateStringsArray, f: (x: <S, T>(p: T) => T) => <S, T>(p: T) => T, h: (x: <S, T>(p: T) => T) => <S, T>(p: T) => T, x: string): string; }
>rest : any[]
return undefined;
>undefined : 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.
tempTag2 `${ x => { x<number>(undefined); return x; } }${ 0 }`;
>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: <T>(p: T) => T) => <T>(p: T) => T, x: number): number; (templateStrs: TemplateStringsArray, f: (x: <S, T>(p: T) => T) => <S, T>(p: T) => T, h: (x: <S, T>(p: T) => T) => <S, T>(p: T) => T, x: string): string; }
>x => { x<number>(undefined); return x; } : (x: <T>(p: T) => T) => <T>(p: T) => T
>x : <T>(p: T) => T
>x<number>(undefined) : number
>x : <T>(p: T) => T
>undefined : undefined
>x : <T>(p: T) => T
tempTag2 `${ x => { x<number, string>(undefined); return x; } }${ y => { y<string, number>(null); return y; } }${ "hello" }`;
>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: <T>(p: T) => T) => <T>(p: T) => T, x: number): number; (templateStrs: TemplateStringsArray, f: (x: <S, T>(p: T) => T) => <S, T>(p: T) => T, h: (x: <S, T>(p: T) => T) => <S, T>(p: T) => T, x: string): string; }
>x => { x<number, string>(undefined); return x; } : (x: <S, T>(p: T) => T) => <S, T>(p: T) => T
>x : <S, T>(p: T) => T
>x<number, string>(undefined) : string
>x : <S, T>(p: T) => T
>undefined : undefined
>x : <S, T>(p: T) => T
>y => { y<string, number>(null); return y; } : (y: <S, T>(p: T) => T) => <S, T>(p: T) => T
>y : <S, T>(p: T) => T
>y<string, number>(null) : number
>y : <S, T>(p: T) => T
>y : <S, T>(p: T) => T
tempTag2 `${ x => { x<number, string>(undefined); return x; } }${ undefined }${ "hello" }`;
>tempTag2 : { (templateStrs: TemplateStringsArray, f: (x: <T>(p: T) => T) => <T>(p: T) => T, x: number): number; (templateStrs: TemplateStringsArray, f: (x: <S, T>(p: T) => T) => <S, T>(p: T) => T, h: (x: <S, T>(p: T) => T) => <S, T>(p: T) => T, x: string): string; }
>x => { x<number, string>(undefined); return x; } : (x: <S, T>(p: T) => T) => <S, T>(p: T) => T
>x : <S, T>(p: T) => T
>x<number, string>(undefined) : string
>x : <S, T>(p: T) => T
>undefined : undefined
>x : <S, T>(p: T) => T
>undefined : undefined
@@ -0,0 +1,15 @@
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 (2 errors) ====
function foo(...rest: any[]) {
}
foo `${function (x: number) { x = "bad"; } }`;
~~~
!!! error TS1159: Tagged templates are only available when targeting ECMAScript 6 and higher.
~
!!! error TS2322: Type 'string' is not assignable to type 'number'.
@@ -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'.
@@ -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";
}}`;
@@ -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'.
@@ -0,0 +1,9 @@
//// [templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.ts]
`${function (x: number) { x = "bad"; } }`;
//// [templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.js]
"" + function (x) {
x = "bad";
};
@@ -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'.
@@ -0,0 +1,8 @@
//// [templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.ts]
`${function (x: number) { x = "bad"; } }`;
//// [templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.js]
`${function (x) {
x = "bad";
}}`;
@@ -0,0 +1,6 @@
function foo(...rest: any[]) {
}
foo `${function (x: number) { x = "bad"; } }`;
@@ -0,0 +1,6 @@
//@target: es6
function foo(...rest: any[]) {
}
foo `${function (x: number) { x = "bad"; } }`;
@@ -0,0 +1,3 @@
`${function (x: number) { x = "bad"; } }`;
@@ -0,0 +1,3 @@
//@target: es6
`${function (x: number) { x = "bad"; } }`;
@@ -0,0 +1,17 @@
// @target: ES6
type FuncType = (x: <T>(p: T) => T) => typeof x;
function tempTag1<T>(templateStrs: TemplateStringsArray, f: FuncType, x: T): T;
function tempTag1<T>(templateStrs: TemplateStringsArray, f: FuncType, h: FuncType, x: T): T;
function tempTag1<T>(...rest: any[]): T {
return 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<number>(undefined); return x; } }${ y => { y<number>(undefined); return y; } }${ 10 }`;
tempTag1 `${ x => { x<number>(undefined); return x; } }${ (y: <T>(p: T) => T) => { y<number>(undefined); return y } }${ undefined }`;
tempTag1 `${ (x: <T>(p: T) => T) => { x<number>(undefined); return x; } }${ y => { y<number>(undefined); return y; } }${ undefined }`;
@@ -0,0 +1,18 @@
// @target: ES6
type FuncType1 = (x: <T>(p: T) => T) => typeof x;
type FuncType2 = (x: <S, T>(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;
}
// 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<number>(undefined); return x; } }${ 0 }`;
tempTag2 `${ x => { x<number, string>(undefined); return x; } }${ y => { y<string, number>(null); return y; } }${ "hello" }`;
tempTag2 `${ x => { x<number, string>(undefined); return x; } }${ undefined }${ "hello" }`;
@@ -0,0 +1,19 @@
/// <reference path="fourslash.ts" />
////function tempTag1<T>(templateStrs: TemplateStringsArray, f: (x: T) => T, x: T): T;
////function tempTag1<T>(templateStrs: TemplateStringsArray, f: (x: T) => T, h: (y: T) => T, x: T): T;
////function tempTag1<T>(...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");
});
@@ -0,0 +1,31 @@
/// <reference path="fourslash.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 => /*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");
}