-
Notifications
You must be signed in to change notification settings - Fork 13.2k
Allow type arguments in generic tagged templates #23430
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 13 commits
b409888
23567ee
60b6d3f
da7967a
090f6bd
7aa916a
4785acb
82e09c9
fe8615d
6107e05
2510c19
eb8eeaf
a2073f1
4bfb1a3
78e98c3
8e27f46
e21a8b8
7f96fec
70feb7b
87bb96d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1032,17 +1032,19 @@ namespace ts { | |
| : node; | ||
| } | ||
|
|
||
| export function createTaggedTemplate(tag: Expression, template: TemplateLiteral) { | ||
| export function createTaggedTemplate(tag: Expression, typeArguments: NodeArray<TypeNode>, template: TemplateLiteral) { | ||
|
||
| const node = <TaggedTemplateExpression>createSynthesizedNode(SyntaxKind.TaggedTemplateExpression); | ||
| node.tag = parenthesizeForAccess(tag); | ||
| node.typeArguments = typeArguments; | ||
| node.template = template; | ||
| return node; | ||
| } | ||
|
|
||
| export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral) { | ||
| export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: NodeArray<TypeNode>, template: TemplateLiteral) { | ||
| return node.tag !== tag | ||
| || node.typeArguments !== typeArguments | ||
| || node.template !== template | ||
| ? updateNode(createTaggedTemplate(tag, template), node) | ||
| ? updateNode(createTaggedTemplate(tag, typeArguments, template), node) | ||
| : node; | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1050,6 +1050,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; | ||
|
|
@@ -3516,8 +3517,8 @@ declare namespace ts { | |
| function updateCall(node: CallExpression, expression: Expression, typeArguments: ReadonlyArray<TypeNode> | undefined, argumentsArray: ReadonlyArray<Expression>): CallExpression; | ||
| 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 updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral): TaggedTemplateExpression; | ||
| function createTaggedTemplate(tag: Expression, typeArguments: NodeArray<TypeNode>, template: TemplateLiteral): TaggedTemplateExpression; | ||
|
||
| function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, typeArguments: NodeArray<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; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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; |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm pretty sure this duplicates the logic in the
else ifbelow, no? You should just need to add to theCallExpressioncast below. (I'd add aCallLikeExpressionWithTypeArguments, that'sCallLikeExpressionsans decorators, which are the only one without them)