GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Allow type arguments in generic tagged templates by DanielRosenwasser · Pull Request #23430 · microsoft/TypeScript

Conversation

@DanielRosenwasser

@DanielRosenwasser Daniel Rosenwasser (DanielRosenwasser) commented Apr 16, 2018 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

This pull request allows users to pass generic type arguments to tagged template strings.

declare function styledComponent<Props>(strs: TemplateStringsArray): Component<Props>;

interface MyProps {
  name: string;
  age: number;
}

styledComponent<MyProps> `
  font-size: 1.5em;
  text-align: center;
  color: palevioletred;
`;

declare function tag<T>(strs: TemplateStringsArray, ...args: T[]): T;

// inference fails because 'number' and 'string' are both candidates that conflict
let a = tag<string | number> `${100} ${"hello"}`;

Fixes #11947

Background

Tagged templates are a form of invocation introduced in ECMAScript 2015. Like call expressions, generic functions may be used in a tagged template and TypeScript will infer the type arguments utilized:

declare function tag<T>(strs: TemplateStringsArray, ...args: T[]): T;

let a = tag(100, 200);     // has type 'number'
let b = tag `Hello world`; // has type TemplateStringsArray

However, in some cases there are no inference candidates

declare function styledComponent<Props>(strs: TemplateStringsArray): Component<Props>

// has type 'Component<{}>' because there were no candidates
let a = styledComponent `
  font-size: 1.5em;
  text-align: center;
  color: palevioletred;
`;

or, type arguments cannot be inferred because TypeScript is conservative in its inferences

declare function tag<T>(strs: TemplateStringsArray, ...args: T[]): T;

// inference fails because 'number' and 'string' are both candidates that conflict
let b = tag `${100} ${"hello"}`;

Parser changes

The core change is a new intermediate grammar production between MemberExpression and CallExpression/NewExpression

TaggedTemplateWithTypeArguments:
    TaggedTemplateWithTypeArguments < TypeArgumentList > TemplateLiteral
    MemberExpression

Then CoverCallExpressionAndAsyncArrowHead (which is the grammar production that currently transitions a CallExpression into a MemberExpression) no longer references MemberExpression Arguments, but instead looks more like:

CoverCallExpressionAndAsyncArrowHead:
    TaggedTemplateWithTypeArguments Arguments

Similarly, NewExpression no longer references MemberExpression, and instead goes for

NewExpression:
    TaggedTemplateWithTypeArguments TypeArgumentsArguments
    new TaggedTemplateWithTypeArguments Arguments

Within our mechanics for MemberExpression still use the following production for tagged template expressions (which you can see in parseMemberExpressionRest)

MemberExpression:
    MemberExpression TemplateLiteral

This way we always try to parse out a template after a MemberExpression, even when there are no type arguments.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

SpaceK33z, beshanoe, Havret, nickbreaton, lucasterra, pawelsmolaga, krzkaczor, kkuriata, xdk78, Piotr-Aueternum, and 14 more reacted with thumbs up emoji MichalLytek, SpaceK33z, beshanoe, Havret, atfzl, nickbreaton, lucasterra, miafoo, Grmiade, krzkaczor, and 17 more reacted with hooray emoji Havret, nickbreaton, lucasterra, sebald, krzkaczor, xdk78, Piotr-Aueternum, beshanoe, Igorbek, ryall, and 8 more reacted with heart emoji
All reactions
  • 👍 24 reactions
  • 🎉 27 reactions
  • ❤️ 18 reactions
Daniel Rosenwasser (DanielRosenwasser) added 13 commits April 13, 2018 23:01
@DanielRosenwasser
Added tests.
b409888
@DanielRosenwasser
Accepted baselines.
23567ee
@DanielRosenwasser
Fixed up test. Thanks arrow functions...
60b6d3f
@DanielRosenwasser
Added basic support for parsing/emitting type arguments in tagged tem…
da7967a
…plate expressions.
@DanielRosenwasser
Accepted baselines.
090f6bd
@DanielRosenwasser
Strip away type arguments from tagged templates when emitting.
7aa916a
@DanielRosenwasser
Accepted baselines.
4785acb
@DanielRosenwasser
Perform checking and resolution of tagged template type arguments.
82e09c9
@DanielRosenwasser
Accepted baselines.
fe8615d
@DanielRosenwasser
Added test for tagged templates in new expressions.
6107e05
@DanielRosenwasser
Accepted baselines.
2510c19
@DanielRosenwasser
Allow parsing tagged templates with type arguments in new expressions.
eb8eeaf
@DanielRosenwasser
Accepted baselines.
a2073f1
@DanielRosenwasser Daniel Rosenwasser (DanielRosenwasser) mentioned this pull request Apr 16, 2018
Support passing generics to tagged template string #11947
Closed
@DanielRosenwasser
Daniel Rosenwasser (DanielRosenwasser) requested review from Ron Buckton (rbuckton), Nathan Shively-Sanders (sandersn) and Wesley Wigham (weswigham) April 16, 2018 16:51
@lucasterra

Lucas Terra (lucasterra) commented Apr 16, 2018

Copy link
Copy Markdown

Beautiful! Thank you :)

rossipedia and DanielRosenwasser reacted with heart emoji
All reactions
  • ❤️ 2 reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@beshanoe beshanoe (beshanoe) mentioned this pull request Apr 16, 2018
How do I provide props to styled elements in Typescript? styled-components/styled-components#630
Closed
@Havret

Krzysztof Porebski (Havret) commented Apr 16, 2018

Copy link
Copy Markdown

Thank you so much! It really made my day. :)

nickbreaton and rossipedia reacted with thumbs up emoji DanielRosenwasser reacted with heart emoji
All reactions
  • 👍 2 reactions
  • ❤️ 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@MartinJohns

Martin Johns (MartinJohns) commented Apr 16, 2018

Copy link
Copy Markdown
Contributor

Can you please also update the spec according to the new changes?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

mhegazy
Mohamed Hegazy (mhegazy) reviewed Apr 17, 2018
View reviewed changes
Comment thread tests/baselines/reference/api/tsserverlibrary.d.ts Outdated
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;

@mhegazy Mohamed Hegazy (mhegazy) Apr 17, 2018

Copy link
Copy Markdown
Contributor

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.

this is an API breaking change. we need to document it

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@mhegazy Mohamed Hegazy (mhegazy) Apr 17, 2018

Copy link
Copy Markdown
Contributor

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.

the other option is to put it at the end, or have multiple overloads. check with Ron Buckton (@rbuckton)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@DanielRosenwasser Daniel Rosenwasser (DanielRosenwasser) Apr 17, 2018

Copy link
Copy Markdown
Member Author

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.

Yeah, I wanted to get the conversation rolling on this one. Every time we change the AST, these factory functions get pretty annoying to update. I wonder whether VMs have gotten good at optimizing the "named arguments" pattern for options-bag style APIs.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
ajafff
Klaus Meinhardt (ajafff) reviewed Apr 17, 2018
View reviewed changes
Comment thread src/compiler/factory.ts Outdated
}

export function createTaggedTemplate(tag: Expression, template: TemplateLiteral) {
export function createTaggedTemplate(tag: Expression, typeArguments: NodeArray<TypeNode>, template: TemplateLiteral) {

@ajafff Klaus Meinhardt (ajafff) Apr 17, 2018

Copy link
Copy Markdown
Contributor

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.

the API would be easier to use if the parameter is typed as ReadonlyArray and it's converted to a NodeArray in the function body.
this also applies to the update function below.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

DanielRosenwasser reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

@DanielRosenwasser Daniel Rosenwasser (DanielRosenwasser) Apr 17, 2018

Copy link
Copy Markdown
Member Author

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.

Good call!

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@ajafff Klaus Meinhardt (ajafff) mentioned this pull request Apr 17, 2018
no-inferred-empty-object: check tagged templates fimbullinter/wotan#190
Closed
@chetmurphy Chet Murphy (chetmurphy) mentioned this pull request Apr 17, 2018
Typescript support styled-system/styled-system#169
Closed
Daniel Rosenwasser (DanielRosenwasser) added 2 commits April 17, 2018 14:09
@DanielRosenwasser
Avoid breaking change by introducing overloads for 'createTaggedTempl…
4bfb1a3
…ate'/'updateTaggedTemplate'.
@DanielRosenwasser
Accepted baselines.
78e98c3
@DanielRosenwasser

Daniel Rosenwasser (DanielRosenwasser) commented Apr 17, 2018 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member Author

Mohamed Hegazy (@mhegazy), the API is purely additive now, minimizing breaking changes.
Klaus Meinhardt (@ajafff), the API now converts ReadonlyArrays to NodeArrays.

Havret and rossipedia reacted with thumbs up emoji
All reactions
  • 👍 2 reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

This was referenced Apr 17, 2018
Type arguments on tagged templates babel/babel#7746
Closed
TypeScript 2.9 meta-issue babel/babel#7747
Closed
@sjiep Robert van Kints (sjiep) mentioned this pull request Apr 18, 2018
Support for "styled-components-ts" styled-components/webstorm-styled-components#45
Closed
@ghost ghost mentioned this pull request Apr 18, 2018
TypeScript: Support type arguments on tagged templates babel/babel#7754
Merged
Daniel Rosenwasser (DanielRosenwasser) added 2 commits April 19, 2018 10:34
@DanielRosenwasser
Added test for ASI concerns.
8e27f46
@DanielRosenwasser
Accepted baselines.
e21a8b8
@DanielRosenwasser Daniel Rosenwasser (DanielRosenwasser) mentioned this pull request Apr 19, 2018
TypeScript 2.9 meta-issue microsoft/TypeScript-TmLanguage#603
Closed
2 of 3 tasks
weswigham
Wesley Wigham (weswigham) reviewed Apr 19, 2018
View reviewed changes
Comment thread src/compiler/checker.ts Outdated
let typeArguments: NodeArray<TypeNode>;

if (!isTaggedTemplate && !isDecorator && !isJsxOpeningOrSelfClosingElement) {
if (isTaggedTemplate) {

@weswigham Wesley Wigham (weswigham) Apr 19, 2018 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

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 if below, no? You should just need to add to the CallExpression cast below. (I'd add a CallLikeExpressionWithTypeArguments, that's CallLikeExpression sans decorators, which are the only one without them)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Daniel Rosenwasser (DanielRosenwasser) added 3 commits April 19, 2018 15:16
@DanielRosenwasser
Added test in case 'super' is ever possibly parsed as a tagged templa…
7f96fec
…te string.
@DanielRosenwasser
Avoid duplicate code when checking for tagged templates.
70feb7b
@DanielRosenwasser
Accepted baselines.
87bb96d
weswigham
Wesley Wigham (weswigham) approved these changes Apr 19, 2018
View reviewed changes
@DanielRosenwasser
Daniel Rosenwasser (DanielRosenwasser) merged commit 84b1291 into master Apr 19, 2018
@DanielRosenwasser
Daniel Rosenwasser (DanielRosenwasser) deleted the taggedTemplateTypeArguments branch April 19, 2018 22:50
@nickbreaton Nick Breaton (nickbreaton) mentioned this pull request Apr 19, 2018
[TypeScript] Implement generics for tagged template literals styled-components/styled-components#1697
Closed
@MartinJohns

Martin Johns (MartinJohns) commented Apr 20, 2018

Copy link
Copy Markdown
Contributor

No update of the spec. :-(

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@sergeysova

Sova (sergeysova) commented Apr 20, 2018

Copy link
Copy Markdown

What about passed functions?

const Example = styled.div`
  font-size: ${p => p.size}rem;
  flex-direction: ${p => p.row ? 'row' : 'column'};
`
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ikatyang Ika (ikatyang) mentioned this pull request Apr 21, 2018
New: support TaggedTemplateExpression typeParameters (fixes #468) eslint/typescript-eslint-parser#469
Merged
@DanielRosenwasser

Daniel Rosenwasser (DanielRosenwasser) commented Apr 24, 2018

Copy link
Copy Markdown
Member Author

Martin Johns (@MartinJohns) it's on my backlog, sorry. 😞

Sergey Shandar (@sergey-shandar) Not sure what you're asking about, but any problems or authoring questions should be filed as a new issue or as a StackOverflow question respectively.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@microsoft Microsoft (microsoft) locked as resolved and limited conversation to collaborators Apr 24, 2018
@microsoft Microsoft (microsoft) unlocked this conversation Apr 24, 2018
@sergey-shandar

Sergey Shandar (sergey-shandar) commented Apr 24, 2018

Copy link
Copy Markdown
Contributor

Daniel Rosenwasser (@DanielRosenwasser) I think you mean Sova (@sergeysova).

DanielRosenwasser reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@AntonioRedondo Antonio Redondo (AntonioRedondo) mentioned this pull request May 2, 2018
Typescript checking error styled-components/styled-components#1428
Closed
@undeadcat Maxim Kropotov (undeadcat) mentioned this pull request Jul 7, 2018
Add generic tagged template literals support styled-components/webstorm-styled-components#50
Closed
Brian Ng (existentialism) pushed a commit to babel/babel that referenced this pull request Jul 26, 2018
Andy @existentialism
TypeScript: Support type arguments on tagged templates (#7754)
8ee24fd
| Q                        | A
| ------------------------ | ---
| Fixed Issues?            | #7747 (partly)
| Patch: Bug Fix?          | 
| Major: Breaking Change?  | 
| Minor: New Feature?      | Yes
| Tests Added + Pass?      | Yes
| Documentation PR         |
| Any Dependency Changes?  |
| License                  | MIT

@JamesHenry This changes the AST format. CC @DanielRosenwasser for review.
Supports parsing type arguments on tagged template calls.
Should wait on microsoft/TypeScript#23430 to be merged so we're sure we have the final syntax.
@microsoft Microsoft (microsoft) locked and limited conversation to collaborators Jul 31, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Reviewers

@weswigham Wesley Wigham (weswigham) weswigham approved these changes
@sandersn Nathan Shively-Sanders (sandersn) Awaiting requested review from sandersn
@rbuckton Ron Buckton (rbuckton) Awaiting requested review from rbuckton
+2 more reviewers
@mhegazy Mohamed Hegazy (mhegazy) mhegazy left review comments
@ajafff Klaus Meinhardt (ajafff) ajafff left review comments
Reviewers whose approvals may not affect merge requirements

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

9 participants

@DanielRosenwasser @lucasterra @Havret @MartinJohns @sergeysova @sergey-shandar @weswigham @mhegazy @ajafff
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.