diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d009a956c43ee..b65d153aa4529 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17749,11 +17749,11 @@ namespace ts { let typeArguments: NodeArray; - if (!isTaggedTemplate && !isDecorator && !isJsxOpeningOrSelfClosingElement) { + if (!isDecorator && !isJsxOpeningOrSelfClosingElement) { typeArguments = (node).typeArguments; // We already perform checking on the type arguments on the class declaration itself. - if ((node).expression.kind !== SyntaxKind.SuperKeyword) { + if (isTaggedTemplate || (node).expression.kind !== SyntaxKind.SuperKeyword) { forEach(typeArguments, checkSourceElement); } } @@ -17866,7 +17866,7 @@ namespace ts { checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, /*excludeArgument*/ undefined, /*reportErrors*/ true); } else if (candidateForTypeArgumentError) { - checkTypeArguments(candidateForTypeArgumentError, (node as CallExpression).typeArguments, /*reportErrors*/ true, fallbackError); + checkTypeArguments(candidateForTypeArgumentError, (node as CallExpression | TaggedTemplateExpression).typeArguments, /*reportErrors*/ true, fallbackError); } else if (typeArguments && every(signatures, sig => length(sig.typeParameters) !== typeArguments.length)) { diagnostics.add(getTypeArgumentArityError(node, signatures, typeArguments)); @@ -18660,6 +18660,7 @@ namespace ts { } function checkTaggedTemplateExpression(node: TaggedTemplateExpression): Type { + checkGrammarTypeArguments(node, node.typeArguments); if (languageVersion < ScriptTarget.ES2015) { checkExternalEmitHelpers(node, ExternalEmitHelpers.MakeTemplateObject); } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 289f332cd33f3..2b01f2fdda1bc 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1462,6 +1462,7 @@ namespace ts { function emitTaggedTemplateExpression(node: TaggedTemplateExpression) { emitExpression(node.tag); + emitTypeArguments(node, node.typeArguments); writeSpace(); emitExpression(node.template); } diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 765c3c9cb4a26..e3191930c0e5e 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -1032,17 +1032,32 @@ namespace ts { : node; } - export function createTaggedTemplate(tag: Expression, template: TemplateLiteral) { + export function createTaggedTemplate(tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; + export function createTaggedTemplate(tag: Expression, typeArguments: ReadonlyArray, template: TemplateLiteral): TaggedTemplateExpression; + /** @internal */ + export function createTaggedTemplate(tag: Expression, typeArgumentsOrTemplate: ReadonlyArray | TemplateLiteral, template?: TemplateLiteral): TaggedTemplateExpression; + export function createTaggedTemplate(tag: Expression, typeArgumentsOrTemplate: ReadonlyArray | TemplateLiteral, template?: TemplateLiteral) { const node = createSynthesizedNode(SyntaxKind.TaggedTemplateExpression); node.tag = parenthesizeForAccess(tag); - node.template = template; + if (template) { + node.typeArguments = asNodeArray(typeArgumentsOrTemplate as ReadonlyArray); + node.template = template!; + } + else { + node.typeArguments = undefined; + node.template = typeArgumentsOrTemplate as TemplateLiteral; + } return node; } - export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral) { + export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; + export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: ReadonlyArray, template: TemplateLiteral): TaggedTemplateExpression; + export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArgumentsOrTemplate: ReadonlyArray | TemplateLiteral, template?: TemplateLiteral) { return node.tag !== tag - || node.template !== template - ? updateNode(createTaggedTemplate(tag, template), node) + || (template + ? node.typeArguments !== typeArgumentsOrTemplate || node.template !== template + : node.typeArguments !== undefined || node.template !== typeArgumentsOrTemplate) + ? updateNode(createTaggedTemplate(tag, typeArgumentsOrTemplate, template), node) : node; } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 74d54ed28fb14..4cf4c6e4c6709 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -223,6 +223,7 @@ namespace ts { visitNodes(cbNode, cbNodes, (node).arguments); case SyntaxKind.TaggedTemplateExpression: return visitNode(cbNode, (node).tag) || + visitNodes(cbNode, cbNodes, (node).typeArguments) || visitNode(cbNode, (node).template); case SyntaxKind.TypeAssertionExpression: return visitNode(cbNode, (node).type) || @@ -4362,13 +4363,8 @@ namespace ts { continue; } - if (token() === SyntaxKind.NoSubstitutionTemplateLiteral || token() === SyntaxKind.TemplateHead) { - const tagExpression = createNode(SyntaxKind.TaggedTemplateExpression, expression.pos); - tagExpression.tag = expression; - tagExpression.template = token() === SyntaxKind.NoSubstitutionTemplateLiteral - ? parseLiteralNode() - : parseTemplateExpression(); - expression = finishNode(tagExpression); + if (isTemplateStartOfTaggedTemplate()) { + expression = parseTaggedTemplateRest(expression, /*typeArguments*/ undefined); continue; } @@ -4376,6 +4372,20 @@ namespace ts { } } + function isTemplateStartOfTaggedTemplate() { + return token() === SyntaxKind.NoSubstitutionTemplateLiteral || token() === SyntaxKind.TemplateHead; + } + + function parseTaggedTemplateRest(tag: LeftHandSideExpression, typeArguments: NodeArray | undefined) { + const tagExpression = createNode(SyntaxKind.TaggedTemplateExpression, tag.pos); + tagExpression.tag = tag; + tagExpression.typeArguments = typeArguments; + tagExpression.template = token() === SyntaxKind.NoSubstitutionTemplateLiteral + ? parseLiteralNode() + : parseTemplateExpression(); + return finishNode(tagExpression); + } + function parseCallExpressionRest(expression: LeftHandSideExpression): LeftHandSideExpression { while (true) { expression = parseMemberExpressionRest(expression); @@ -4389,6 +4399,11 @@ namespace ts { return expression; } + if (isTemplateStartOfTaggedTemplate()) { + expression = parseTaggedTemplateRest(expression, typeArguments); + continue; + } + const callExpr = createNode(SyntaxKind.CallExpression, expression.pos); callExpr.expression = expression; callExpr.typeArguments = typeArguments; @@ -4436,8 +4451,10 @@ namespace ts { function canFollowTypeArgumentsInExpression(): boolean { switch (token()) { case SyntaxKind.OpenParenToken: // foo( - // this case are the only case where this token can legally follow a type argument - // list. So we definitely want to treat this as a type arg list. + case SyntaxKind.NoSubstitutionTemplateLiteral: // foo `...` + case SyntaxKind.TemplateHead: // foo `...${100}...` + // these are the only tokens can legally follow a type argument + // list. So we definitely want to treat them as type arg lists. case SyntaxKind.DotToken: // foo. case SyntaxKind.CloseParenToken: // foo) @@ -4666,9 +4683,23 @@ namespace ts { return finishNode(node); } + let expression: MemberExpression = parsePrimaryExpression(); + let typeArguments; + while (true) { + expression = parseMemberExpressionRest(expression); + typeArguments = tryParse(parseTypeArgumentsInExpression); + if (isTemplateStartOfTaggedTemplate()) { + Debug.assert(!!typeArguments, + "Expected a type argument list; all plain tagged template starts should be consumed in 'parseMemberExpressionRest'"); + expression = parseTaggedTemplateRest(expression, typeArguments); + typeArguments = undefined; + } + break; + } + const node = createNode(SyntaxKind.NewExpression, fullStart); - node.expression = parseMemberExpressionOrHigher(); - node.typeArguments = tryParse(parseTypeArgumentsInExpression); + node.expression = expression; + node.typeArguments = typeArguments; if (node.typeArguments || token() === SyntaxKind.OpenParenToken) { node.arguments = parseArgumentList(); } diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 6cb4be16c74ac..f29829d46078e 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -502,6 +502,9 @@ namespace ts { case SyntaxKind.NewExpression: return visitNewExpression(node); + case SyntaxKind.TaggedTemplateExpression: + return visitTaggedTemplateExpression(node); + case SyntaxKind.NonNullExpression: // TypeScript non-null expressions are removed, but their subtrees are preserved. return visitNonNullExpression(node); @@ -2547,6 +2550,14 @@ namespace ts { visitNodes(node.arguments, visitor, isExpression)); } + function visitTaggedTemplateExpression(node: TaggedTemplateExpression) { + return updateTaggedTemplate( + node, + visitNode(node.tag, visitor, isExpression), + /*typeArguments*/ undefined, + visitNode(node.template, visitor, isExpression)); + } + /** * Determines whether to emit an enum declaration. * diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 987d403e7cd9e..f96ea05cb12d7 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1726,6 +1726,7 @@ namespace ts { export interface TaggedTemplateExpression extends MemberExpression { kind: SyntaxKind.TaggedTemplateExpression; tag: LeftHandSideExpression; + typeArguments?: NodeArray; template: TemplateLiteral; } diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 7a70eb02e8e97..284d870caa1e6 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -478,6 +478,7 @@ namespace ts { case SyntaxKind.TaggedTemplateExpression: return updateTaggedTemplate(node, visitNode((node).tag, visitor, isExpression), + visitNodes((node).typeArguments, visitor, isExpression), visitNode((node).template, visitor, isTemplateLiteral)); case SyntaxKind.TypeAssertionExpression: diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 2e8e3f3871df3..06ecede8c881e 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -1050,6 +1050,7 @@ declare namespace ts { interface TaggedTemplateExpression extends MemberExpression { kind: SyntaxKind.TaggedTemplateExpression; tag: LeftHandSideExpression; + typeArguments?: NodeArray; template: TemplateLiteral; } type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression | Decorator | JsxOpeningLikeElement; @@ -3517,7 +3518,9 @@ declare namespace ts { function createNew(expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): NewExpression; function updateNew(node: NewExpression, expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): NewExpression; function createTaggedTemplate(tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; + function createTaggedTemplate(tag: Expression, typeArguments: ReadonlyArray, template: TemplateLiteral): TaggedTemplateExpression; function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; + function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: ReadonlyArray, template: TemplateLiteral): TaggedTemplateExpression; function createTypeAssertion(type: TypeNode, expression: Expression): TypeAssertion; function updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression): TypeAssertion; function createParen(expression: Expression): ParenthesizedExpression; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 378949d5b5b07..9d99813cfe17d 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -1050,6 +1050,7 @@ declare namespace ts { interface TaggedTemplateExpression extends MemberExpression { kind: SyntaxKind.TaggedTemplateExpression; tag: LeftHandSideExpression; + typeArguments?: NodeArray; template: TemplateLiteral; } type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression | Decorator | JsxOpeningLikeElement; @@ -3517,7 +3518,9 @@ declare namespace ts { function createNew(expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): NewExpression; function updateNew(node: NewExpression, expression: Expression, typeArguments: ReadonlyArray | undefined, argumentsArray: ReadonlyArray | undefined): NewExpression; function createTaggedTemplate(tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; + function createTaggedTemplate(tag: Expression, typeArguments: ReadonlyArray, template: TemplateLiteral): TaggedTemplateExpression; function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; + function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: ReadonlyArray, template: TemplateLiteral): TaggedTemplateExpression; function createTypeAssertion(type: TypeNode, expression: Expression): TypeAssertion; function updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression): TypeAssertion; function createParen(expression: Expression): ParenthesizedExpression; diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.js b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.js new file mode 100644 index 0000000000000..b31d327020813 --- /dev/null +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.js @@ -0,0 +1,72 @@ +//// [taggedTemplatesWithTypeArguments1.ts] +declare function f(strs: TemplateStringsArray, ...callbacks: Array<(x: T) => any>): void; + +interface Stuff { + x: number; + y: string; + z: boolean; +} + +export const a = f ` + hello + ${stuff => stuff.x} + brave + ${stuff => stuff.y} + world + ${stuff => stuff.z} +`; + +declare function g( + strs: TemplateStringsArray, + t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V): T | U | V; + +export const b = g ` + hello + ${stuff => stuff.x} + brave + ${stuff => stuff.y} + world + ${stuff => stuff.z} +`; + +declare let obj: { + prop: (strs: TemplateStringsArray, x: (input: T) => T) => { + returnedObjProp: T + } +} + +export let c = obj["prop"] `${(input) => ({ ...input })}` +c.returnedObjProp.x; +c.returnedObjProp.y; +c.returnedObjProp.z; + +c = obj.prop `${(input) => ({ ...input })}` +c.returnedObjProp.x; +c.returnedObjProp.y; +c.returnedObjProp.z; + +//// [taggedTemplatesWithTypeArguments1.js] +export const a = f ` + hello + ${stuff => stuff.x} + brave + ${stuff => stuff.y} + world + ${stuff => stuff.z} +`; +export const b = g ` + hello + ${stuff => stuff.x} + brave + ${stuff => stuff.y} + world + ${stuff => stuff.z} +`; +export let c = obj["prop"] `${(input) => ({ ...input })}`; +c.returnedObjProp.x; +c.returnedObjProp.y; +c.returnedObjProp.z; +c = obj.prop `${(input) => ({ ...input })}`; +c.returnedObjProp.x; +c.returnedObjProp.y; +c.returnedObjProp.z; diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.symbols b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.symbols new file mode 100644 index 0000000000000..798d2e18c68ac --- /dev/null +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.symbols @@ -0,0 +1,186 @@ +=== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts === +declare function f(strs: TemplateStringsArray, ...callbacks: Array<(x: T) => any>): void; +>f : Symbol(f, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 0)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 19)) +>strs : Symbol(strs, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 22)) +>TemplateStringsArray : Symbol(TemplateStringsArray, Decl(lib.es5.d.ts, --, --)) +>callbacks : Symbol(callbacks, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 49)) +>Array : Symbol(Array, Decl(lib.es2016.array.include.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --) ... and 1 more) +>x : Symbol(x, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 71)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 19)) + +interface Stuff { +>Stuff : Symbol(Stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 92)) + + x: number; +>x : Symbol(Stuff.x, Decl(taggedTemplatesWithTypeArguments1.ts, 2, 17)) + + y: string; +>y : Symbol(Stuff.y, Decl(taggedTemplatesWithTypeArguments1.ts, 3, 14)) + + z: boolean; +>z : Symbol(Stuff.z, Decl(taggedTemplatesWithTypeArguments1.ts, 4, 14)) +} + +export const a = f ` +>a : Symbol(a, Decl(taggedTemplatesWithTypeArguments1.ts, 8, 12)) +>f : Symbol(f, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 0)) +>Stuff : Symbol(Stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 92)) + + hello + ${stuff => stuff.x} +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 10, 6)) +>stuff.x : Symbol(Stuff.x, Decl(taggedTemplatesWithTypeArguments1.ts, 2, 17)) +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 10, 6)) +>x : Symbol(Stuff.x, Decl(taggedTemplatesWithTypeArguments1.ts, 2, 17)) + + brave + ${stuff => stuff.y} +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 12, 6)) +>stuff.y : Symbol(Stuff.y, Decl(taggedTemplatesWithTypeArguments1.ts, 3, 14)) +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 12, 6)) +>y : Symbol(Stuff.y, Decl(taggedTemplatesWithTypeArguments1.ts, 3, 14)) + + world + ${stuff => stuff.z} +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 14, 6)) +>stuff.z : Symbol(Stuff.z, Decl(taggedTemplatesWithTypeArguments1.ts, 4, 14)) +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 14, 6)) +>z : Symbol(Stuff.z, Decl(taggedTemplatesWithTypeArguments1.ts, 4, 14)) + +`; + +declare function g( +>g : Symbol(g, Decl(taggedTemplatesWithTypeArguments1.ts, 15, 2)) +>Input : Symbol(Input, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 19)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 25)) +>U : Symbol(U, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 28)) +>V : Symbol(V, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 31)) + + strs: TemplateStringsArray, +>strs : Symbol(strs, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 35)) +>TemplateStringsArray : Symbol(TemplateStringsArray, Decl(lib.es5.d.ts, --, --)) + + t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V): T | U | V; +>t : Symbol(t, Decl(taggedTemplatesWithTypeArguments1.ts, 18, 31)) +>i : Symbol(i, Decl(taggedTemplatesWithTypeArguments1.ts, 19, 8)) +>Input : Symbol(Input, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 19)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 25)) +>u : Symbol(u, Decl(taggedTemplatesWithTypeArguments1.ts, 19, 23)) +>i : Symbol(i, Decl(taggedTemplatesWithTypeArguments1.ts, 19, 28)) +>Input : Symbol(Input, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 19)) +>U : Symbol(U, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 28)) +>v : Symbol(v, Decl(taggedTemplatesWithTypeArguments1.ts, 19, 43)) +>i : Symbol(i, Decl(taggedTemplatesWithTypeArguments1.ts, 19, 48)) +>Input : Symbol(Input, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 19)) +>V : Symbol(V, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 31)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 25)) +>U : Symbol(U, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 28)) +>V : Symbol(V, Decl(taggedTemplatesWithTypeArguments1.ts, 17, 31)) + +export const b = g ` +>b : Symbol(b, Decl(taggedTemplatesWithTypeArguments1.ts, 21, 12)) +>g : Symbol(g, Decl(taggedTemplatesWithTypeArguments1.ts, 15, 2)) +>Stuff : Symbol(Stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 92)) + + hello + ${stuff => stuff.x} +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 23, 6)) +>stuff.x : Symbol(Stuff.x, Decl(taggedTemplatesWithTypeArguments1.ts, 2, 17)) +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 23, 6)) +>x : Symbol(Stuff.x, Decl(taggedTemplatesWithTypeArguments1.ts, 2, 17)) + + brave + ${stuff => stuff.y} +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 25, 6)) +>stuff.y : Symbol(Stuff.y, Decl(taggedTemplatesWithTypeArguments1.ts, 3, 14)) +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 25, 6)) +>y : Symbol(Stuff.y, Decl(taggedTemplatesWithTypeArguments1.ts, 3, 14)) + + world + ${stuff => stuff.z} +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 27, 6)) +>stuff.z : Symbol(Stuff.z, Decl(taggedTemplatesWithTypeArguments1.ts, 4, 14)) +>stuff : Symbol(stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 27, 6)) +>z : Symbol(Stuff.z, Decl(taggedTemplatesWithTypeArguments1.ts, 4, 14)) + +`; + +declare let obj: { +>obj : Symbol(obj, Decl(taggedTemplatesWithTypeArguments1.ts, 30, 11)) + + prop: (strs: TemplateStringsArray, x: (input: T) => T) => { +>prop : Symbol(prop, Decl(taggedTemplatesWithTypeArguments1.ts, 30, 18)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 11)) +>strs : Symbol(strs, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 14)) +>TemplateStringsArray : Symbol(TemplateStringsArray, Decl(lib.es5.d.ts, --, --)) +>x : Symbol(x, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 41)) +>input : Symbol(input, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 46)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 11)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 11)) + + returnedObjProp: T +>returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 11)) + } +} + +export let c = obj["prop"] `${(input) => ({ ...input })}` +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) +>obj : Symbol(obj, Decl(taggedTemplatesWithTypeArguments1.ts, 30, 11)) +>"prop" : Symbol(prop, Decl(taggedTemplatesWithTypeArguments1.ts, 30, 18)) +>Stuff : Symbol(Stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 92)) +>input : Symbol(input, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 38)) +>input : Symbol(input, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 38)) + +c.returnedObjProp.x; +>c.returnedObjProp.x : Symbol(Stuff.x, Decl(taggedTemplatesWithTypeArguments1.ts, 2, 17)) +>c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) +>returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>x : Symbol(Stuff.x, Decl(taggedTemplatesWithTypeArguments1.ts, 2, 17)) + +c.returnedObjProp.y; +>c.returnedObjProp.y : Symbol(Stuff.y, Decl(taggedTemplatesWithTypeArguments1.ts, 3, 14)) +>c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) +>returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>y : Symbol(Stuff.y, Decl(taggedTemplatesWithTypeArguments1.ts, 3, 14)) + +c.returnedObjProp.z; +>c.returnedObjProp.z : Symbol(Stuff.z, Decl(taggedTemplatesWithTypeArguments1.ts, 4, 14)) +>c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) +>returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>z : Symbol(Stuff.z, Decl(taggedTemplatesWithTypeArguments1.ts, 4, 14)) + +c = obj.prop `${(input) => ({ ...input })}` +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) +>obj.prop : Symbol(prop, Decl(taggedTemplatesWithTypeArguments1.ts, 30, 18)) +>obj : Symbol(obj, Decl(taggedTemplatesWithTypeArguments1.ts, 30, 11)) +>prop : Symbol(prop, Decl(taggedTemplatesWithTypeArguments1.ts, 30, 18)) +>Stuff : Symbol(Stuff, Decl(taggedTemplatesWithTypeArguments1.ts, 0, 92)) +>input : Symbol(input, Decl(taggedTemplatesWithTypeArguments1.ts, 41, 24)) +>input : Symbol(input, Decl(taggedTemplatesWithTypeArguments1.ts, 41, 24)) + +c.returnedObjProp.x; +>c.returnedObjProp.x : Symbol(Stuff.x, Decl(taggedTemplatesWithTypeArguments1.ts, 2, 17)) +>c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) +>returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>x : Symbol(Stuff.x, Decl(taggedTemplatesWithTypeArguments1.ts, 2, 17)) + +c.returnedObjProp.y; +>c.returnedObjProp.y : Symbol(Stuff.y, Decl(taggedTemplatesWithTypeArguments1.ts, 3, 14)) +>c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) +>returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>y : Symbol(Stuff.y, Decl(taggedTemplatesWithTypeArguments1.ts, 3, 14)) + +c.returnedObjProp.z; +>c.returnedObjProp.z : Symbol(Stuff.z, Decl(taggedTemplatesWithTypeArguments1.ts, 4, 14)) +>c.returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments1.ts, 36, 10)) +>returnedObjProp : Symbol(returnedObjProp, Decl(taggedTemplatesWithTypeArguments1.ts, 31, 66)) +>z : Symbol(Stuff.z, Decl(taggedTemplatesWithTypeArguments1.ts, 4, 14)) + diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments1.types b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.types new file mode 100644 index 0000000000000..afa83c1b89051 --- /dev/null +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments1.types @@ -0,0 +1,208 @@ +=== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts === +declare function f(strs: TemplateStringsArray, ...callbacks: Array<(x: T) => any>): void; +>f : (strs: TemplateStringsArray, ...callbacks: ((x: T) => any)[]) => void +>T : T +>strs : TemplateStringsArray +>TemplateStringsArray : TemplateStringsArray +>callbacks : ((x: T) => any)[] +>Array : T[] +>x : T +>T : T + +interface Stuff { +>Stuff : Stuff + + x: number; +>x : number + + y: string; +>y : string + + z: boolean; +>z : boolean +} + +export const a = f ` +>a : void +>f ` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : void +>f : (strs: TemplateStringsArray, ...callbacks: ((x: T) => any)[]) => void +>Stuff : Stuff +>` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : string + + hello + ${stuff => stuff.x} +>stuff => stuff.x : (stuff: Stuff) => number +>stuff : Stuff +>stuff.x : number +>stuff : Stuff +>x : number + + brave + ${stuff => stuff.y} +>stuff => stuff.y : (stuff: Stuff) => string +>stuff : Stuff +>stuff.y : string +>stuff : Stuff +>y : string + + world + ${stuff => stuff.z} +>stuff => stuff.z : (stuff: Stuff) => boolean +>stuff : Stuff +>stuff.z : boolean +>stuff : Stuff +>z : boolean + +`; + +declare function g( +>g : (strs: TemplateStringsArray, t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V) => T | U | V +>Input : Input +>T : T +>U : U +>V : V + + strs: TemplateStringsArray, +>strs : TemplateStringsArray +>TemplateStringsArray : TemplateStringsArray + + t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V): T | U | V; +>t : (i: Input) => T +>i : Input +>Input : Input +>T : T +>u : (i: Input) => U +>i : Input +>Input : Input +>U : U +>v : (i: Input) => V +>i : Input +>Input : Input +>V : V +>T : T +>U : U +>V : V + +export const b = g ` +>b : string | number | boolean +>g ` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : string | number | boolean +>g : (strs: TemplateStringsArray, t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V) => T | U | V +>Stuff : Stuff +>` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : string + + hello + ${stuff => stuff.x} +>stuff => stuff.x : (stuff: Stuff) => number +>stuff : Stuff +>stuff.x : number +>stuff : Stuff +>x : number + + brave + ${stuff => stuff.y} +>stuff => stuff.y : (stuff: Stuff) => string +>stuff : Stuff +>stuff.y : string +>stuff : Stuff +>y : string + + world + ${stuff => stuff.z} +>stuff => stuff.z : (stuff: Stuff) => boolean +>stuff : Stuff +>stuff.z : boolean +>stuff : Stuff +>z : boolean + +`; + +declare let obj: { +>obj : { prop: (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; }; } + + prop: (strs: TemplateStringsArray, x: (input: T) => T) => { +>prop : (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; } +>T : T +>strs : TemplateStringsArray +>TemplateStringsArray : TemplateStringsArray +>x : (input: T) => T +>input : T +>T : T +>T : T + + returnedObjProp: T +>returnedObjProp : T +>T : T + } +} + +export let c = obj["prop"] `${(input) => ({ ...input })}` +>c : { returnedObjProp: Stuff; } +>obj["prop"] `${(input) => ({ ...input })}` : { returnedObjProp: Stuff; } +>obj["prop"] : (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; } +>obj : { prop: (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; }; } +>"prop" : "prop" +>Stuff : Stuff +>`${(input) => ({ ...input })}` : string +>(input) => ({ ...input }) : (input: Stuff) => { x: number; y: string; z: boolean; } +>input : Stuff +>({ ...input }) : { x: number; y: string; z: boolean; } +>{ ...input } : { x: number; y: string; z: boolean; } +>input : Stuff + +c.returnedObjProp.x; +>c.returnedObjProp.x : number +>c.returnedObjProp : Stuff +>c : { returnedObjProp: Stuff; } +>returnedObjProp : Stuff +>x : number + +c.returnedObjProp.y; +>c.returnedObjProp.y : string +>c.returnedObjProp : Stuff +>c : { returnedObjProp: Stuff; } +>returnedObjProp : Stuff +>y : string + +c.returnedObjProp.z; +>c.returnedObjProp.z : boolean +>c.returnedObjProp : Stuff +>c : { returnedObjProp: Stuff; } +>returnedObjProp : Stuff +>z : boolean + +c = obj.prop `${(input) => ({ ...input })}` +>c = obj.prop `${(input) => ({ ...input })}` : { returnedObjProp: Stuff; } +>c : { returnedObjProp: Stuff; } +>obj.prop `${(input) => ({ ...input })}` : { returnedObjProp: Stuff; } +>obj.prop : (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; } +>obj : { prop: (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; }; } +>prop : (strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; } +>Stuff : Stuff +>`${(input) => ({ ...input })}` : string +>(input) => ({ ...input }) : (input: Stuff) => { x: number; y: string; z: boolean; } +>input : Stuff +>({ ...input }) : { x: number; y: string; z: boolean; } +>{ ...input } : { x: number; y: string; z: boolean; } +>input : Stuff + +c.returnedObjProp.x; +>c.returnedObjProp.x : number +>c.returnedObjProp : Stuff +>c : { returnedObjProp: Stuff; } +>returnedObjProp : Stuff +>x : number + +c.returnedObjProp.y; +>c.returnedObjProp.y : string +>c.returnedObjProp : Stuff +>c : { returnedObjProp: Stuff; } +>returnedObjProp : Stuff +>y : string + +c.returnedObjProp.z; +>c.returnedObjProp.z : boolean +>c.returnedObjProp : Stuff +>c : { returnedObjProp: Stuff; } +>returnedObjProp : Stuff +>z : boolean + diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt new file mode 100644 index 0000000000000..4460743303153 --- /dev/null +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.errors.txt @@ -0,0 +1,61 @@ +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(13,30): error TS2345: Argument of type '"hello"' is not assignable to parameter of type 'number'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(15,11): error TS2347: Untyped function calls may not accept type arguments. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(17,30): error TS2345: Argument of type '"hello"' is not assignable to parameter of type 'number'. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(35,5): error TS2377: Constructors for derived classes must contain a 'super' call. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(36,9): error TS17011: 'super' must be called before accessing a property of 'super' in the constructor of a derived class. +tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts(36,14): error TS1034: 'super' must be followed by an argument list or member access. + + +==== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts (6 errors) ==== + export interface SomethingTaggable { + (t: TemplateStringsArray, ...args: T[]): SomethingNewable; + } + + export interface SomethingNewable { + new (...args: T[]): any; + } + + declare const tag: SomethingTaggable; + + const a = new tag `${100} ${200}`("hello", "world"); + + const b = new tag `${"hello"} ${"world"}`(100, 200); + ~~~~~~~ +!!! error TS2345: Argument of type '"hello"' is not assignable to parameter of type 'number'. + + const c = new tag `${100} ${200}`("hello", "world"); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2347: Untyped function calls may not accept type arguments. + + const d = new tag `${"hello"} ${"world"}`(100, 200); + ~~~~~~~ +!!! error TS2345: Argument of type '"hello"' is not assignable to parameter of type 'number'. + + /** + * Testing ASI. This should never parse as + * + * ```ts + * new tag; + * `hello${369}`(); + * ``` + */ + const e = new tag + `hello`(); + + class SomeBase { + a!: A; b!: B; c!: C; + } + + class SomeDerived extends SomeBase { + constructor() { + ~~~~~~~~~~~~~~~ + super `hello world`; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~~~~~ +!!! error TS17011: 'super' must be called before accessing a property of 'super' in the constructor of a derived class. + ~ +!!! error TS1034: 'super' must be followed by an argument list or member access. + } + ~~~~~ +!!! error TS2377: Constructors for derived classes must contain a 'super' call. + } \ No newline at end of file diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js new file mode 100644 index 0000000000000..bc170467fa8be --- /dev/null +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.js @@ -0,0 +1,61 @@ +//// [taggedTemplatesWithTypeArguments2.ts] +export interface SomethingTaggable { + (t: TemplateStringsArray, ...args: T[]): SomethingNewable; +} + +export interface SomethingNewable { + new (...args: T[]): any; +} + +declare const tag: SomethingTaggable; + +const a = new tag `${100} ${200}`("hello", "world"); + +const b = new tag `${"hello"} ${"world"}`(100, 200); + +const c = new tag `${100} ${200}`("hello", "world"); + +const d = new tag `${"hello"} ${"world"}`(100, 200); + +/** + * Testing ASI. This should never parse as + * + * ```ts + * new tag; + * `hello${369}`(); + * ``` + */ +const e = new tag +`hello`(); + +class SomeBase { + a!: A; b!: B; c!: C; +} + +class SomeDerived extends SomeBase { + constructor() { + super `hello world`; + } +} + +//// [taggedTemplatesWithTypeArguments2.js] +const a = new tag `${100} ${200}`("hello", "world"); +const b = new tag `${"hello"} ${"world"}`(100, 200); +const c = (new tag `${100} ${200}`)("hello", "world"); +const d = (new tag `${"hello"} ${"world"}`)(100, 200); +/** + * Testing ASI. This should never parse as + * + * ```ts + * new tag; + * `hello${369}`(); + * ``` + */ +const e = new tag `hello`(); +class SomeBase { +} +class SomeDerived extends SomeBase { + constructor() { + super. `hello world`; + } +} diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.symbols b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.symbols new file mode 100644 index 0000000000000..631770a30ddc7 --- /dev/null +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.symbols @@ -0,0 +1,83 @@ +=== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts === +export interface SomethingTaggable { +>SomethingTaggable : Symbol(SomethingTaggable, Decl(taggedTemplatesWithTypeArguments2.ts, 0, 0)) + + (t: TemplateStringsArray, ...args: T[]): SomethingNewable; +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments2.ts, 1, 5)) +>t : Symbol(t, Decl(taggedTemplatesWithTypeArguments2.ts, 1, 8)) +>TemplateStringsArray : Symbol(TemplateStringsArray, Decl(lib.es5.d.ts, --, --)) +>args : Symbol(args, Decl(taggedTemplatesWithTypeArguments2.ts, 1, 32)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments2.ts, 1, 5)) +>SomethingNewable : Symbol(SomethingNewable, Decl(taggedTemplatesWithTypeArguments2.ts, 2, 1)) +} + +export interface SomethingNewable { +>SomethingNewable : Symbol(SomethingNewable, Decl(taggedTemplatesWithTypeArguments2.ts, 2, 1)) + + new (...args: T[]): any; +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments2.ts, 5, 9)) +>args : Symbol(args, Decl(taggedTemplatesWithTypeArguments2.ts, 5, 12)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments2.ts, 5, 9)) +} + +declare const tag: SomethingTaggable; +>tag : Symbol(tag, Decl(taggedTemplatesWithTypeArguments2.ts, 8, 13)) +>SomethingTaggable : Symbol(SomethingTaggable, Decl(taggedTemplatesWithTypeArguments2.ts, 0, 0)) + +const a = new tag `${100} ${200}`("hello", "world"); +>a : Symbol(a, Decl(taggedTemplatesWithTypeArguments2.ts, 10, 5)) +>tag : Symbol(tag, Decl(taggedTemplatesWithTypeArguments2.ts, 8, 13)) + +const b = new tag `${"hello"} ${"world"}`(100, 200); +>b : Symbol(b, Decl(taggedTemplatesWithTypeArguments2.ts, 12, 5)) +>tag : Symbol(tag, Decl(taggedTemplatesWithTypeArguments2.ts, 8, 13)) + +const c = new tag `${100} ${200}`("hello", "world"); +>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments2.ts, 14, 5)) +>tag : Symbol(tag, Decl(taggedTemplatesWithTypeArguments2.ts, 8, 13)) + +const d = new tag `${"hello"} ${"world"}`(100, 200); +>d : Symbol(d, Decl(taggedTemplatesWithTypeArguments2.ts, 16, 5)) +>tag : Symbol(tag, Decl(taggedTemplatesWithTypeArguments2.ts, 8, 13)) + +/** + * Testing ASI. This should never parse as + * + * ```ts + * new tag; + * `hello${369}`(); + * ``` + */ +const e = new tag +>e : Symbol(e, Decl(taggedTemplatesWithTypeArguments2.ts, 26, 5)) +>tag : Symbol(tag, Decl(taggedTemplatesWithTypeArguments2.ts, 8, 13)) + +`hello`(); + +class SomeBase { +>SomeBase : Symbol(SomeBase, Decl(taggedTemplatesWithTypeArguments2.ts, 27, 10)) +>A : Symbol(A, Decl(taggedTemplatesWithTypeArguments2.ts, 29, 15)) +>B : Symbol(B, Decl(taggedTemplatesWithTypeArguments2.ts, 29, 17)) +>C : Symbol(C, Decl(taggedTemplatesWithTypeArguments2.ts, 29, 20)) + + a!: A; b!: B; c!: C; +>a : Symbol(SomeBase.a, Decl(taggedTemplatesWithTypeArguments2.ts, 29, 25)) +>A : Symbol(A, Decl(taggedTemplatesWithTypeArguments2.ts, 29, 15)) +>b : Symbol(SomeBase.b, Decl(taggedTemplatesWithTypeArguments2.ts, 30, 10)) +>B : Symbol(B, Decl(taggedTemplatesWithTypeArguments2.ts, 29, 17)) +>c : Symbol(SomeBase.c, Decl(taggedTemplatesWithTypeArguments2.ts, 30, 17)) +>C : Symbol(C, Decl(taggedTemplatesWithTypeArguments2.ts, 29, 20)) +} + +class SomeDerived extends SomeBase { +>SomeDerived : Symbol(SomeDerived, Decl(taggedTemplatesWithTypeArguments2.ts, 31, 1)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments2.ts, 33, 18)) +>SomeBase : Symbol(SomeBase, Decl(taggedTemplatesWithTypeArguments2.ts, 27, 10)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments2.ts, 33, 18)) + + constructor() { + super `hello world`; +>super : Symbol(SomeBase, Decl(taggedTemplatesWithTypeArguments2.ts, 27, 10)) +>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments2.ts, 33, 18)) + } +} diff --git a/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types new file mode 100644 index 0000000000000..8aef2009d1b4f --- /dev/null +++ b/tests/baselines/reference/taggedTemplatesWithTypeArguments2.types @@ -0,0 +1,120 @@ +=== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts === +export interface SomethingTaggable { +>SomethingTaggable : SomethingTaggable + + (t: TemplateStringsArray, ...args: T[]): SomethingNewable; +>T : T +>t : TemplateStringsArray +>TemplateStringsArray : TemplateStringsArray +>args : T[] +>T : T +>SomethingNewable : SomethingNewable +} + +export interface SomethingNewable { +>SomethingNewable : SomethingNewable + + new (...args: T[]): any; +>T : T +>args : T[] +>T : T +} + +declare const tag: SomethingTaggable; +>tag : SomethingTaggable +>SomethingTaggable : SomethingTaggable + +const a = new tag `${100} ${200}`("hello", "world"); +>a : any +>new tag `${100} ${200}`("hello", "world") : any +>tag `${100} ${200}` : SomethingNewable +>tag : SomethingTaggable +>`${100} ${200}` : string +>100 : 100 +>200 : 200 +>"hello" : "hello" +>"world" : "world" + +const b = new tag `${"hello"} ${"world"}`(100, 200); +>b : any +>new tag `${"hello"} ${"world"}`(100, 200) : any +>tag `${"hello"} ${"world"}` : any +>tag : SomethingTaggable +>`${"hello"} ${"world"}` : string +>"hello" : "hello" +>"world" : "world" +>100 : 100 +>200 : 200 + +const c = new tag `${100} ${200}`("hello", "world"); +>c : any +>new tag `${100} ${200}`("hello", "world") : any +>new tag `${100} ${200}` : any +>tag `${100} ${200}` : SomethingNewable +>tag : SomethingTaggable +>`${100} ${200}` : string +>100 : 100 +>200 : 200 +>"hello" : "hello" +>"world" : "world" + +const d = new tag `${"hello"} ${"world"}`(100, 200); +>d : any +>new tag `${"hello"} ${"world"}`(100, 200) : any +>new tag `${"hello"} ${"world"}` : any +>tag `${"hello"} ${"world"}` : any +>tag : SomethingTaggable +>`${"hello"} ${"world"}` : string +>"hello" : "hello" +>"world" : "world" +>100 : 100 +>200 : 200 + +/** + * Testing ASI. This should never parse as + * + * ```ts + * new tag; + * `hello${369}`(); + * ``` + */ +const e = new tag +>e : any +>new tag`hello`() : any +>tag`hello` : SomethingNewable +>tag : SomethingTaggable + +`hello`(); +>`hello` : "hello" + +class SomeBase { +>SomeBase : SomeBase +>A : A +>B : B +>C : C + + a!: A; b!: B; c!: C; +>a : A +>A : A +>b : B +>B : B +>c : C +>C : C +} + +class SomeDerived extends SomeBase { +>SomeDerived : SomeDerived +>T : T +>SomeBase : SomeBase +>T : T + + constructor() { + super `hello world`; +>super `hello world` : any +>super : any +>super : SomeBase +> : any +>T : T +>`hello world` : "hello world" + } +} diff --git a/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts b/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts new file mode 100644 index 0000000000000..2f3fc71e65d04 --- /dev/null +++ b/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts @@ -0,0 +1,47 @@ +// @target: esnext + +declare function f(strs: TemplateStringsArray, ...callbacks: Array<(x: T) => any>): void; + +interface Stuff { + x: number; + y: string; + z: boolean; +} + +export const a = f ` + hello + ${stuff => stuff.x} + brave + ${stuff => stuff.y} + world + ${stuff => stuff.z} +`; + +declare function g( + strs: TemplateStringsArray, + t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V): T | U | V; + +export const b = g ` + hello + ${stuff => stuff.x} + brave + ${stuff => stuff.y} + world + ${stuff => stuff.z} +`; + +declare let obj: { + prop: (strs: TemplateStringsArray, x: (input: T) => T) => { + returnedObjProp: T + } +} + +export let c = obj["prop"] `${(input) => ({ ...input })}` +c.returnedObjProp.x; +c.returnedObjProp.y; +c.returnedObjProp.z; + +c = obj.prop `${(input) => ({ ...input })}` +c.returnedObjProp.x; +c.returnedObjProp.y; +c.returnedObjProp.z; \ No newline at end of file diff --git a/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts b/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts new file mode 100644 index 0000000000000..a7a0044d93dcf --- /dev/null +++ b/tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts @@ -0,0 +1,41 @@ +// @target: esnext +// @strict: true + +export interface SomethingTaggable { + (t: TemplateStringsArray, ...args: T[]): SomethingNewable; +} + +export interface SomethingNewable { + new (...args: T[]): any; +} + +declare const tag: SomethingTaggable; + +const a = new tag `${100} ${200}`("hello", "world"); + +const b = new tag `${"hello"} ${"world"}`(100, 200); + +const c = new tag `${100} ${200}`("hello", "world"); + +const d = new tag `${"hello"} ${"world"}`(100, 200); + +/** + * Testing ASI. This should never parse as + * + * ```ts + * new tag; + * `hello${369}`(); + * ``` + */ +const e = new tag +`hello`(); + +class SomeBase { + a!: A; b!: B; c!: C; +} + +class SomeDerived extends SomeBase { + constructor() { + super `hello world`; + } +} \ No newline at end of file