Merge pull request #23430 from Microsoft/taggedTemplateTypeArguments

Allow type arguments in generic tagged templates
This commit is contained in:
Daniel Rosenwasser 2018-04-19 15:50:19 -07:00 committed by GitHub
commit 84b12910e8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 965 additions and 19 deletions

View file

@ -17749,11 +17749,11 @@ namespace ts {
let typeArguments: NodeArray<TypeNode>;
if (!isTaggedTemplate && !isDecorator && !isJsxOpeningOrSelfClosingElement) {
if (!isDecorator && !isJsxOpeningOrSelfClosingElement) {
typeArguments = (<CallExpression>node).typeArguments;
// We already perform checking on the type arguments on the class declaration itself.
if ((<CallExpression>node).expression.kind !== SyntaxKind.SuperKeyword) {
if (isTaggedTemplate || (<CallExpression>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);
}

View file

@ -1462,6 +1462,7 @@ namespace ts {
function emitTaggedTemplateExpression(node: TaggedTemplateExpression) {
emitExpression(node.tag);
emitTypeArguments(node, node.typeArguments);
writeSpace();
emitExpression(node.template);
}

View file

@ -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<TypeNode>, template: TemplateLiteral): TaggedTemplateExpression;
/** @internal */
export function createTaggedTemplate(tag: Expression, typeArgumentsOrTemplate: ReadonlyArray<TypeNode> | TemplateLiteral, template?: TemplateLiteral): TaggedTemplateExpression;
export function createTaggedTemplate(tag: Expression, typeArgumentsOrTemplate: ReadonlyArray<TypeNode> | TemplateLiteral, template?: TemplateLiteral) {
const node = <TaggedTemplateExpression>createSynthesizedNode(SyntaxKind.TaggedTemplateExpression);
node.tag = parenthesizeForAccess(tag);
node.template = template;
if (template) {
node.typeArguments = asNodeArray(typeArgumentsOrTemplate as ReadonlyArray<TypeNode>);
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<TypeNode>, template: TemplateLiteral): TaggedTemplateExpression;
export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArgumentsOrTemplate: ReadonlyArray<TypeNode> | 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;
}

View file

@ -223,6 +223,7 @@ namespace ts {
visitNodes(cbNode, cbNodes, (<CallExpression>node).arguments);
case SyntaxKind.TaggedTemplateExpression:
return visitNode(cbNode, (<TaggedTemplateExpression>node).tag) ||
visitNodes(cbNode, cbNodes, (<TaggedTemplateExpression>node).typeArguments) ||
visitNode(cbNode, (<TaggedTemplateExpression>node).template);
case SyntaxKind.TypeAssertionExpression:
return visitNode(cbNode, (<TypeAssertion>node).type) ||
@ -4362,13 +4363,8 @@ namespace ts {
continue;
}
if (token() === SyntaxKind.NoSubstitutionTemplateLiteral || token() === SyntaxKind.TemplateHead) {
const tagExpression = <TaggedTemplateExpression>createNode(SyntaxKind.TaggedTemplateExpression, expression.pos);
tagExpression.tag = expression;
tagExpression.template = token() === SyntaxKind.NoSubstitutionTemplateLiteral
? <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<TypeNode> | undefined) {
const tagExpression = <TaggedTemplateExpression>createNode(SyntaxKind.TaggedTemplateExpression, tag.pos);
tagExpression.tag = tag;
tagExpression.typeArguments = typeArguments;
tagExpression.template = token() === SyntaxKind.NoSubstitutionTemplateLiteral
? <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 = <CallExpression>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<x>(
// 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<T> `...`
case SyntaxKind.TemplateHead: // foo<T> `...${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<x>.
case SyntaxKind.CloseParenToken: // foo<x>)
@ -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 = <NewExpression>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();
}

View file

@ -502,6 +502,9 @@ namespace ts {
case SyntaxKind.NewExpression:
return visitNewExpression(<NewExpression>node);
case SyntaxKind.TaggedTemplateExpression:
return visitTaggedTemplateExpression(<TaggedTemplateExpression>node);
case SyntaxKind.NonNullExpression:
// TypeScript non-null expressions are removed, but their subtrees are preserved.
return visitNonNullExpression(<NonNullExpression>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.
*

View file

@ -1727,6 +1727,7 @@ namespace ts {
export interface TaggedTemplateExpression extends MemberExpression {
kind: SyntaxKind.TaggedTemplateExpression;
tag: LeftHandSideExpression;
typeArguments?: NodeArray<TypeNode>;
template: TemplateLiteral;
}

View file

@ -478,6 +478,7 @@ namespace ts {
case SyntaxKind.TaggedTemplateExpression:
return updateTaggedTemplate(<TaggedTemplateExpression>node,
visitNode((<TaggedTemplateExpression>node).tag, visitor, isExpression),
visitNodes((<TaggedTemplateExpression>node).typeArguments, visitor, isExpression),
visitNode((<TaggedTemplateExpression>node).template, visitor, isTemplateLiteral));
case SyntaxKind.TypeAssertionExpression:

View file

@ -1051,6 +1051,7 @@ declare namespace ts {
interface TaggedTemplateExpression extends MemberExpression {
kind: SyntaxKind.TaggedTemplateExpression;
tag: LeftHandSideExpression;
typeArguments?: NodeArray<TypeNode>;
template: TemplateLiteral;
}
type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression | Decorator | JsxOpeningLikeElement;
@ -3524,7 +3525,9 @@ declare namespace ts {
function createNew(expression: Expression, typeArguments: ReadonlyArray<TypeNode> | undefined, argumentsArray: ReadonlyArray<Expression> | undefined): NewExpression;
function updateNew(node: NewExpression, expression: Expression, typeArguments: ReadonlyArray<TypeNode> | undefined, argumentsArray: ReadonlyArray<Expression> | undefined): NewExpression;
function createTaggedTemplate(tag: Expression, template: TemplateLiteral): TaggedTemplateExpression;
function createTaggedTemplate(tag: Expression, typeArguments: ReadonlyArray<TypeNode>, template: TemplateLiteral): TaggedTemplateExpression;
function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral): TaggedTemplateExpression;
function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: ReadonlyArray<TypeNode>, template: TemplateLiteral): TaggedTemplateExpression;
function createTypeAssertion(type: TypeNode, expression: Expression): TypeAssertion;
function updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression): TypeAssertion;
function createParen(expression: Expression): ParenthesizedExpression;

View file

@ -1051,6 +1051,7 @@ declare namespace ts {
interface TaggedTemplateExpression extends MemberExpression {
kind: SyntaxKind.TaggedTemplateExpression;
tag: LeftHandSideExpression;
typeArguments?: NodeArray<TypeNode>;
template: TemplateLiteral;
}
type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression | Decorator | JsxOpeningLikeElement;
@ -3524,7 +3525,9 @@ declare namespace ts {
function createNew(expression: Expression, typeArguments: ReadonlyArray<TypeNode> | undefined, argumentsArray: ReadonlyArray<Expression> | undefined): NewExpression;
function updateNew(node: NewExpression, expression: Expression, typeArguments: ReadonlyArray<TypeNode> | undefined, argumentsArray: ReadonlyArray<Expression> | undefined): NewExpression;
function createTaggedTemplate(tag: Expression, template: TemplateLiteral): TaggedTemplateExpression;
function createTaggedTemplate(tag: Expression, typeArguments: ReadonlyArray<TypeNode>, template: TemplateLiteral): TaggedTemplateExpression;
function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral): TaggedTemplateExpression;
function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: ReadonlyArray<TypeNode>, template: TemplateLiteral): TaggedTemplateExpression;
function createTypeAssertion(type: TypeNode, expression: Expression): TypeAssertion;
function updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression): TypeAssertion;
function createParen(expression: Expression): ParenthesizedExpression;

View file

@ -0,0 +1,72 @@
//// [taggedTemplatesWithTypeArguments1.ts]
declare function f<T>(strs: TemplateStringsArray, ...callbacks: Array<(x: T) => any>): void;
interface Stuff {
x: number;
y: string;
z: boolean;
}
export const a = f<Stuff> `
hello
${stuff => stuff.x}
brave
${stuff => stuff.y}
world
${stuff => stuff.z}
`;
declare function g<Input, T, U, V>(
strs: TemplateStringsArray,
t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V): T | U | V;
export const b = g<Stuff, number, string, boolean> `
hello
${stuff => stuff.x}
brave
${stuff => stuff.y}
world
${stuff => stuff.z}
`;
declare let obj: {
prop: <T>(strs: TemplateStringsArray, x: (input: T) => T) => {
returnedObjProp: T
}
}
export let c = obj["prop"]<Stuff> `${(input) => ({ ...input })}`
c.returnedObjProp.x;
c.returnedObjProp.y;
c.returnedObjProp.z;
c = obj.prop<Stuff> `${(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;

View file

@ -0,0 +1,186 @@
=== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts ===
declare function f<T>(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<Stuff> `
>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<Input, T, U, V>(
>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<Stuff, number, string, boolean> `
>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: <T>(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"]<Stuff> `${(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<Stuff> `${(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))

View file

@ -0,0 +1,208 @@
=== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments1.ts ===
declare function f<T>(strs: TemplateStringsArray, ...callbacks: Array<(x: T) => any>): void;
>f : <T>(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<Stuff> `
>a : void
>f<Stuff> ` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : void
>f : <T>(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<Input, T, U, V>(
>g : <Input, T, U, V>(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<Stuff, number, string, boolean> `
>b : string | number | boolean
>g<Stuff, number, string, boolean> ` hello ${stuff => stuff.x} brave ${stuff => stuff.y} world ${stuff => stuff.z}` : string | number | boolean
>g : <Input, T, U, V>(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: <T>(strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; }; }
prop: <T>(strs: TemplateStringsArray, x: (input: T) => T) => {
>prop : <T>(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"]<Stuff> `${(input) => ({ ...input })}`
>c : { returnedObjProp: Stuff; }
>obj["prop"]<Stuff> `${(input) => ({ ...input })}` : { returnedObjProp: Stuff; }
>obj["prop"] : <T>(strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; }
>obj : { prop: <T>(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<Stuff> `${(input) => ({ ...input })}`
>c = obj.prop<Stuff> `${(input) => ({ ...input })}` : { returnedObjProp: Stuff; }
>c : { returnedObjProp: Stuff; }
>obj.prop<Stuff> `${(input) => ({ ...input })}` : { returnedObjProp: Stuff; }
>obj.prop : <T>(strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; }
>obj : { prop: <T>(strs: TemplateStringsArray, x: (input: T) => T) => { returnedObjProp: T; }; }
>prop : <T>(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

View file

@ -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>(t: TemplateStringsArray, ...args: T[]): SomethingNewable;
}
export interface SomethingNewable {
new <T>(...args: T[]): any;
}
declare const tag: SomethingTaggable;
const a = new tag `${100} ${200}`<string>("hello", "world");
const b = new tag<number> `${"hello"} ${"world"}`(100, 200);
~~~~~~~
!!! error TS2345: Argument of type '"hello"' is not assignable to parameter of type 'number'.
const c = new tag<number> `${100} ${200}`<string>("hello", "world");
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2347: Untyped function calls may not accept type arguments.
const d = new tag<number> `${"hello"} ${"world"}`<string>(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<number>;
* `hello${369}`();
* ```
*/
const e = new tag<number>
`hello`();
class SomeBase<A, B, C> {
a!: A; b!: B; c!: C;
}
class SomeDerived<T> extends SomeBase<number, string, T> {
constructor() {
~~~~~~~~~~~~~~~
super<number, string, T> `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.
}

View file

@ -0,0 +1,61 @@
//// [taggedTemplatesWithTypeArguments2.ts]
export interface SomethingTaggable {
<T>(t: TemplateStringsArray, ...args: T[]): SomethingNewable;
}
export interface SomethingNewable {
new <T>(...args: T[]): any;
}
declare const tag: SomethingTaggable;
const a = new tag `${100} ${200}`<string>("hello", "world");
const b = new tag<number> `${"hello"} ${"world"}`(100, 200);
const c = new tag<number> `${100} ${200}`<string>("hello", "world");
const d = new tag<number> `${"hello"} ${"world"}`<string>(100, 200);
/**
* Testing ASI. This should never parse as
*
* ```ts
* new tag<number>;
* `hello${369}`();
* ```
*/
const e = new tag<number>
`hello`();
class SomeBase<A, B, C> {
a!: A; b!: B; c!: C;
}
class SomeDerived<T> extends SomeBase<number, string, T> {
constructor() {
super<number, string, T> `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<number>;
* `hello${369}`();
* ```
*/
const e = new tag `hello`();
class SomeBase {
}
class SomeDerived extends SomeBase {
constructor() {
super. `hello world`;
}
}

View file

@ -0,0 +1,83 @@
=== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts ===
export interface SomethingTaggable {
>SomethingTaggable : Symbol(SomethingTaggable, Decl(taggedTemplatesWithTypeArguments2.ts, 0, 0))
<T>(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 <T>(...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}`<string>("hello", "world");
>a : Symbol(a, Decl(taggedTemplatesWithTypeArguments2.ts, 10, 5))
>tag : Symbol(tag, Decl(taggedTemplatesWithTypeArguments2.ts, 8, 13))
const b = new tag<number> `${"hello"} ${"world"}`(100, 200);
>b : Symbol(b, Decl(taggedTemplatesWithTypeArguments2.ts, 12, 5))
>tag : Symbol(tag, Decl(taggedTemplatesWithTypeArguments2.ts, 8, 13))
const c = new tag<number> `${100} ${200}`<string>("hello", "world");
>c : Symbol(c, Decl(taggedTemplatesWithTypeArguments2.ts, 14, 5))
>tag : Symbol(tag, Decl(taggedTemplatesWithTypeArguments2.ts, 8, 13))
const d = new tag<number> `${"hello"} ${"world"}`<string>(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<number>;
* `hello${369}`();
* ```
*/
const e = new tag<number>
>e : Symbol(e, Decl(taggedTemplatesWithTypeArguments2.ts, 26, 5))
>tag : Symbol(tag, Decl(taggedTemplatesWithTypeArguments2.ts, 8, 13))
`hello`();
class SomeBase<A, B, C> {
>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<T> extends SomeBase<number, string, T> {
>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<number, string, T> `hello world`;
>super : Symbol(SomeBase, Decl(taggedTemplatesWithTypeArguments2.ts, 27, 10))
>T : Symbol(T, Decl(taggedTemplatesWithTypeArguments2.ts, 33, 18))
}
}

View file

@ -0,0 +1,120 @@
=== tests/cases/conformance/es6/templates/taggedTemplatesWithTypeArguments2.ts ===
export interface SomethingTaggable {
>SomethingTaggable : SomethingTaggable
<T>(t: TemplateStringsArray, ...args: T[]): SomethingNewable;
>T : T
>t : TemplateStringsArray
>TemplateStringsArray : TemplateStringsArray
>args : T[]
>T : T
>SomethingNewable : SomethingNewable
}
export interface SomethingNewable {
>SomethingNewable : SomethingNewable
new <T>(...args: T[]): any;
>T : T
>args : T[]
>T : T
}
declare const tag: SomethingTaggable;
>tag : SomethingTaggable
>SomethingTaggable : SomethingTaggable
const a = new tag `${100} ${200}`<string>("hello", "world");
>a : any
>new tag `${100} ${200}`<string>("hello", "world") : any
>tag `${100} ${200}` : SomethingNewable
>tag : SomethingTaggable
>`${100} ${200}` : string
>100 : 100
>200 : 200
>"hello" : "hello"
>"world" : "world"
const b = new tag<number> `${"hello"} ${"world"}`(100, 200);
>b : any
>new tag<number> `${"hello"} ${"world"}`(100, 200) : any
>tag<number> `${"hello"} ${"world"}` : any
>tag : SomethingTaggable
>`${"hello"} ${"world"}` : string
>"hello" : "hello"
>"world" : "world"
>100 : 100
>200 : 200
const c = new tag<number> `${100} ${200}`<string>("hello", "world");
>c : any
>new tag<number> `${100} ${200}`<string>("hello", "world") : any
>new tag<number> `${100} ${200}` : any
>tag<number> `${100} ${200}` : SomethingNewable
>tag : SomethingTaggable
>`${100} ${200}` : string
>100 : 100
>200 : 200
>"hello" : "hello"
>"world" : "world"
const d = new tag<number> `${"hello"} ${"world"}`<string>(100, 200);
>d : any
>new tag<number> `${"hello"} ${"world"}`<string>(100, 200) : any
>new tag<number> `${"hello"} ${"world"}` : any
>tag<number> `${"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<number>;
* `hello${369}`();
* ```
*/
const e = new tag<number>
>e : any
>new tag<number>`hello`() : any
>tag<number>`hello` : SomethingNewable
>tag : SomethingTaggable
`hello`();
>`hello` : "hello"
class SomeBase<A, B, C> {
>SomeBase : SomeBase<A, B, C>
>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<T> extends SomeBase<number, string, T> {
>SomeDerived : SomeDerived<T>
>T : T
>SomeBase : SomeBase<number, string, T>
>T : T
constructor() {
super<number, string, T> `hello world`;
>super<number, string, T> `hello world` : any
>super : any
>super : SomeBase<number, string, T>
> : any
>T : T
>`hello world` : "hello world"
}
}

View file

@ -0,0 +1,47 @@
// @target: esnext
declare function f<T>(strs: TemplateStringsArray, ...callbacks: Array<(x: T) => any>): void;
interface Stuff {
x: number;
y: string;
z: boolean;
}
export const a = f<Stuff> `
hello
${stuff => stuff.x}
brave
${stuff => stuff.y}
world
${stuff => stuff.z}
`;
declare function g<Input, T, U, V>(
strs: TemplateStringsArray,
t: (i: Input) => T, u: (i: Input) => U, v: (i: Input) => V): T | U | V;
export const b = g<Stuff, number, string, boolean> `
hello
${stuff => stuff.x}
brave
${stuff => stuff.y}
world
${stuff => stuff.z}
`;
declare let obj: {
prop: <T>(strs: TemplateStringsArray, x: (input: T) => T) => {
returnedObjProp: T
}
}
export let c = obj["prop"]<Stuff> `${(input) => ({ ...input })}`
c.returnedObjProp.x;
c.returnedObjProp.y;
c.returnedObjProp.z;
c = obj.prop<Stuff> `${(input) => ({ ...input })}`
c.returnedObjProp.x;
c.returnedObjProp.y;
c.returnedObjProp.z;

View file

@ -0,0 +1,41 @@
// @target: esnext
// @strict: true
export interface SomethingTaggable {
<T>(t: TemplateStringsArray, ...args: T[]): SomethingNewable;
}
export interface SomethingNewable {
new <T>(...args: T[]): any;
}
declare const tag: SomethingTaggable;
const a = new tag `${100} ${200}`<string>("hello", "world");
const b = new tag<number> `${"hello"} ${"world"}`(100, 200);
const c = new tag<number> `${100} ${200}`<string>("hello", "world");
const d = new tag<number> `${"hello"} ${"world"}`<string>(100, 200);
/**
* Testing ASI. This should never parse as
*
* ```ts
* new tag<number>;
* `hello${369}`();
* ```
*/
const e = new tag<number>
`hello`();
class SomeBase<A, B, C> {
a!: A; b!: B; c!: C;
}
class SomeDerived<T> extends SomeBase<number, string, T> {
constructor() {
super<number, string, T> `hello world`;
}
}