FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Support relations and inference between template literal types by ahejlsberg · Pull Request #43361 · microsoft/TypeScript · GitHub

Support relations and inference between template literal types - #43361

Merged
Anders Hejlsberg (ahejlsberg) merged 5 commits into
masterfrom
fix43060
Mar 28, 2021
Merged

Support relations and inference between template literal types#43361
Anders Hejlsberg (ahejlsberg) merged 5 commits into
masterfrom
fix43060

Conversation

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.

Comment thread src/compiler/checker.ts
const matches: Type[] = [];
let seg = 0;
let pos = targetStartText.length;
for (let i = 1; i < lastTargetIndex; i++) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

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

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

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

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Ok, I'll add some comments.

Comment thread src/compiler/checker.ts
}

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

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Would it be useful to have a singleton emptyTemplateType?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

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.

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 {

Daniel Rosenwasser (DanielRosenwasser) Mar 26, 2021
edited
Loading

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

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.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

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.

Daniel Rosenwasser (DanielRosenwasser) Mar 28, 2021
edited
Loading

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

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.

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

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

Projects

None yet

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}

4 participants


Back | FazBrowse Home | New Git URL