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 — Support relations and inference between template literal types by ahejlsberg · Pull Request #43361 · microsoft/TypeScript

Conversation

@ahejlsberg

@ahejlsberg Anders Hejlsberg (ahejlsberg) commented Mar 24, 2021

Copy link
Copy Markdown
Member

With this PR we support relations and inference between template literal types. Specifically, when the target side in a type relation is a template literal type, the source side is now permitted to be a compatible (i.e. more specific) template literal type. Likewise, when inferring to a template literal target type, we now permit the source type to also be a template literal type.

Some examples of improved assignment relations:

declare let s1: `${number}-${number}-${number}`;
declare let s2: `1-2-3`;
declare let s3: `${number}-2-3`;
declare let s4: `1-${number}-3`;
declare let s5: `1-2-${number}`;
declare let s6: `${number}-2-${number}`;
s1 = s2;
s1 = s3;
s1 = s4;
s1 = s5;
s1 = s6;

With this PR all of the above assignments are permitted, where previously only the first assignment was permitted.

Some examples of inference between template literal types:

declare function foo1<V extends string>(arg: `*${V}*`): V;

function test<T extends string>(s: string, n: number, b: boolean, t: T) {
    let x1 = foo('*hello*');  // "hello"
    let x2 = foo('**hello**');  // "*hello*"
    let x3 = foo(`*${s}*` as const);  // string
    let x4 = foo(`*${n}*` as const);  // `${number}`
    let x5 = foo(`*${b}*` as const);  // "true" | "false"
    let x6 = foo(`*${t}*` as const);  // `${T}`
    let x7 = foo(`**${s}**` as const);  // `*${string}*`
}

Fixes #43060.
Fixes #43243.

Sorry, something went wrong.

Uh oh!

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

kotarella1110, bluebill1049, millsp, jcalz, whzx5byb, cyrto, mateja176, Fi1osof, WillAvudim, tjjfvi, and 2 more reacted with hooray emoji tonivj5, earthlyreason, KisaragiEffective, kotarella1110, bluebill1049, jcalz, cyrto, epidemian, Fi1osof, WillAvudim, and tjjfvi reacted with heart emoji AviVahl, cyrto, havok187, bluebill1049, Fi1osof, WillAvudim, and tjjfvi reacted with rocket emoji bluebill1049, cyrto, havok187, and mateuscalza reacted with eyes emoji
All reactions
  • 🎉 12 reactions
  • ❤️ 11 reactions
  • 🚀 7 reactions
  • 👀 4 reactions
Anders Hejlsberg (ahejlsberg) added 3 commits March 24, 2021 09:25
@ahejlsberg
Support assignment and inference between template literal types
0e58dcf
@ahejlsberg
Add tests
fd2284b
@ahejlsberg
Accept new baselines
2b6b910
@typescript-bot TypeScript Bot (typescript-bot) assigned Anders Hejlsberg (ahejlsberg) Mar 24, 2021
@typescript-bot TypeScript Bot (typescript-bot) added Author: Team For Uncommitted Bug PR for untriaged, rejected, closed or missing bug labels Mar 24, 2021
@ahejlsberg
Anders Hejlsberg (ahejlsberg) requested review from Daniel Rosenwasser (DanielRosenwasser) and Ryan Cavanaugh (RyanCavanaugh) March 24, 2021 16:53
@ahejlsberg Anders Hejlsberg (ahejlsberg) added this to the TypeScript 4.3.1 milestone Mar 24, 2021
@ahejlsberg
Merge branch 'master' into fix43060
510ee0c
RyanCavanaugh
Ryan Cavanaugh (RyanCavanaugh) reviewed Mar 26, 2021
View reviewed changes
Comment thread src/compiler/checker.ts
const matches: Type[] = [];
let seg = 0;
let pos = targetStartText.length;
for (let i = 1; i < lastTargetIndex; i++) {

@RyanCavanaugh Ryan Cavanaugh (RyanCavanaugh) Mar 26, 2021

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.

Some sort of comment (an overview of the algorithm / what it's trying to do, or the name of it if this is a well-known one?) seems justified here

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) Mar 26, 2021

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.

Yes, I think if you could just explain with examples too, that'd be helpful.

Sorry, something went wrong.

Uh oh!

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

All reactions

@ahejlsberg Anders Hejlsberg (ahejlsberg) Mar 28, 2021

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.

Ok, I'll add some comments.

Sorry, something went wrong.

Uh oh!

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

All reactions
RyanCavanaugh
Ryan Cavanaugh (RyanCavanaugh) approved these changes Mar 26, 2021
View reviewed changes
DanielRosenwasser
Daniel Rosenwasser (DanielRosenwasser) reviewed Mar 26, 2021
View reviewed changes
Comment thread src/compiler/checker.ts
}

function getStringLikeTypeForType(type: Type) {
return type.flags & (TypeFlags.Any | TypeFlags.StringLike) ? type : getTemplateLiteralType(["", ""], [type]);

@DanielRosenwasser Daniel Rosenwasser (DanielRosenwasser) Mar 26, 2021

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.

Would it be useful to have a singleton emptyTemplateType?

Sorry, something went wrong.

Uh oh!

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

All reactions

@ahejlsberg Anders Hejlsberg (ahejlsberg) Mar 28, 2021

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.

Well, the single-element types array varies here, so we can't use a singleton. We could possibly have a singleton for the ["", ""] array, but it's hardly worth the effort as this code doesn't run that often.

Sorry, something went wrong.

Uh oh!

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

All reactions
DanielRosenwasser
Daniel Rosenwasser (DanielRosenwasser) reviewed Mar 26, 2021
View reviewed changes
Comment thread src/compiler/checker.ts
return type.flags & (TypeFlags.Any | TypeFlags.StringLike) ? type : getTemplateLiteralType(["", ""], [type]);
}

function inferFromLiteralPartsToTemplateLiteral(sourceTexts: readonly string[], sourceTypes: readonly Type[], target: TemplateLiteralType): Type[] | undefined {

@DanielRosenwasser Daniel Rosenwasser (DanielRosenwasser) Mar 26, 2021 •
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 don't like calling these sourceTexts because it immediately signals to me "BUG" even though you're not actually grabbing out the source text. You're grabbing the normalized text content which is the correct thing to do.

Sorry, something went wrong.

Uh oh!

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

All reactions

@ahejlsberg Anders Hejlsberg (ahejlsberg) Mar 28, 2021

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.

Hmm, I don't think the current names are that bad. After all the properties are called texts and types in template literals and we want the parameters to reflect the relation.

Sorry, something went wrong.

Uh oh!

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

All reactions

@DanielRosenwasser Daniel Rosenwasser (DanielRosenwasser) Mar 28, 2021 •
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.

Right, I think that even texts would be a better name - I may send a follow-up PR but I'm going to merge this for now.

Sorry, something went wrong.

Uh oh!

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

All reactions
@ahejlsberg
Add comments
f098498
@ahejlsberg
Anders Hejlsberg (ahejlsberg) merged commit 4774666 into master Mar 28, 2021
@ahejlsberg
Anders Hejlsberg (ahejlsberg) deleted the fix43060 branch March 28, 2021 20:12
@DanielRosenwasser Daniel Rosenwasser (DanielRosenwasser) mentioned this pull request Apr 7, 2021
Design Meeting Notes, 3/26/2021 #43581
Closed
This was referenced Apr 12, 2021
The issue of: Type 'string' is not assignable to type '${string} | ${string}.${string} | ${string}.${number}'. react-hook-form/react-hook-form#4748
Closed
V7: Controller value type and watch type is never when using watch inside a Field array react-hook-form/react-hook-form#4853
Closed
@bluebill1049 Bill (bluebill1049) mentioned this pull request Apr 26, 2021
V7 FieldArray Typescript template string error react-hook-form/react-hook-form#4917
Closed
@DanielRosenwasser Daniel Rosenwasser (DanielRosenwasser) mentioned this pull request May 1, 2021
Infer Subtypes from Template Literal Types #43907
Closed
5 tasks done
@johnrom John Rom (johnrom) mentioned this pull request May 3, 2021
Strongly Typed Formik, v3 jaredpalmer/formik#3152
Draft
4 of 10 tasks
@bluebill1049 Bill (bluebill1049) mentioned this pull request May 24, 2021
Nested Field Array Items are not correctly typed react-hook-form/react-hook-form#5318
Closed
@microsoft Microsoft (microsoft) locked as resolved and limited conversation to collaborators Oct 21, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Reviewers

@DanielRosenwasser Daniel Rosenwasser (DanielRosenwasser) DanielRosenwasser left review comments
@RyanCavanaugh Ryan Cavanaugh (RyanCavanaugh) RyanCavanaugh approved these changes

Uh oh!

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

Assignees

@ahejlsberg Anders Hejlsberg (ahejlsberg)

Labels

Author: Team For Uncommitted Bug PR for untriaged, rejected, closed or missing bug

Projects

None yet

Milestone

TypeScript 4.3.1

Development

Successfully merging this pull request may close these issues.

Template literal expression is not assignable to matching template literal type Cannot infer Template Literal Type containing ${number} / ${string}

Uh oh!

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

4 participants

@ahejlsberg @DanielRosenwasser @RyanCavanaugh @typescript-bot
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.