Merge pull request #23430 from Microsoft/taggedTemplateTypeArguments
Allow type arguments in generic tagged templates
This commit is contained in:
commit
84b12910e8
18 changed files with 965 additions and 19 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -1462,6 +1462,7 @@ namespace ts {
|
|||
|
||||
function emitTaggedTemplateExpression(node: TaggedTemplateExpression) {
|
||||
emitExpression(node.tag);
|
||||
emitTypeArguments(node, node.typeArguments);
|
||||
writeSpace();
|
||||
emitExpression(node.template);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -1727,6 +1727,7 @@ namespace ts {
|
|||
export interface TaggedTemplateExpression extends MemberExpression {
|
||||
kind: SyntaxKind.TaggedTemplateExpression;
|
||||
tag: LeftHandSideExpression;
|
||||
typeArguments?: NodeArray<TypeNode>;
|
||||
template: TemplateLiteral;
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
|
@ -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))
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
}
|
|
@ -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`;
|
||||
}
|
||||
}
|
|
@ -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))
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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;
|
|
@ -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`;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue