mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge pull request #1492 from Microsoft/contextualTemplateTyping
Fixed contextual type resolution and type checking for tagged template expressions.
This commit is contained in:
+20
-7
@@ -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
|
||||
|
||||
+15
@@ -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'.
|
||||
+11
@@ -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'.
|
||||
+17
@@ -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";
|
||||
}}`;
|
||||
+9
@@ -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'.
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
//// [templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.ts]
|
||||
|
||||
|
||||
`${function (x: number) { x = "bad"; } }`;
|
||||
|
||||
//// [templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpression.js]
|
||||
"" + function (x) {
|
||||
x = "bad";
|
||||
};
|
||||
+8
@@ -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'.
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
//// [templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.ts]
|
||||
|
||||
`${function (x: number) { x = "bad"; } }`;
|
||||
|
||||
//// [templateStringsWithTypeErrorInFunctionExpressionsInSubstitutionExpressionES6.js]
|
||||
`${function (x) {
|
||||
x = "bad";
|
||||
}}`;
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
|
||||
|
||||
function foo(...rest: any[]) {
|
||||
}
|
||||
|
||||
foo `${function (x: number) { x = "bad"; } }`;
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
//@target: es6
|
||||
|
||||
function foo(...rest: any[]) {
|
||||
}
|
||||
|
||||
foo `${function (x: number) { x = "bad"; } }`;
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
|
||||
|
||||
`${function (x: number) { x = "bad"; } }`;
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
//@target: es6
|
||||
|
||||
`${function (x: number) { x = "bad"; } }`;
|
||||
+17
@@ -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 }`;
|
||||
+18
@@ -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" }`;
|
||||
+19
@@ -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");
|
||||
});
|
||||
+31
@@ -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");
|
||||
}
|
||||
Reference in New Issue
Block a user