Allow intersections to be used as valid types for template literal placeholders#54188
Conversation
|
Couple of things:
|
…valid-types-for-template-literal-placeholders # Conflicts: # tests/baselines/reference/templateLiteralTypesPatterns.errors.txt
done
Reading through some of the recent design notes (here)... it's still unclear if/when/how the team is going to pick up this. This PR though doesn't introduce a lot of extra support for those "special intersections" - it fixes assignability issues when they are involved. This is a clear bug from the assignability PoV: function conversionTest(groupName: | "downcast" | "dataDowncast" | "editingDowncast" | `${string & {}}Downcast`) {}
conversionTest("testDowncast"); // error but should be OKSome other cases are improved with it as well, like this one: function foo(str: `${`a${string}` & `${string}a`}Test`) {}
foo("abaTest"); // error but should be OK |
0a12f3e to
f5f1403
Compare
This comment was marked as duplicate.
This comment was marked as duplicate.
|
@typescript-bot test this |
|
Heya @gabritto, I've started to run the diff-based top-repos suite (tsserver) on this PR at f5f1403. You can monitor the build here. Update: The results are in! |
|
Heya @gabritto, I've started to run the diff-based user code test suite (tsserver) on this PR at f5f1403. You can monitor the build here. Update: The results are in! |
|
Heya @gabritto, I've started to run the perf test suite on this PR at f5f1403. You can monitor the build here. Update: The results are in! |
|
Heya @gabritto, I've started to run the parallelized Definitely Typed test suite on this PR at f5f1403. You can monitor the build here. Update: The results are in! |
|
Heya @gabritto, I've started to run the diff-based top-repos suite on this PR at f5f1403. You can monitor the build here. Update: The results are in! |
|
Heya @gabritto, I've started to run the diff-based user code test suite on this PR at f5f1403. You can monitor the build here. Update: The results are in! |
|
@typescript-bot pack this |
|
Hey @gabritto, I've packed this into an installable tgz. You can install it for testing by referencing it in your and then running There is also a playground for this build and an npm module you can use via |
|
@gabritto Here are the results of running the user test suite comparing Everything looks good! |
|
@gabritto Here are the results of running the user test suite comparing There were infrastructure failures potentially unrelated to your change:
Otherwise... Something interesting changed - please have a look. Details
|
| return true; | ||
| } | ||
| if (target.flags & TypeFlags.Intersection) { | ||
| return every((target as IntersectionType).types, t => t === emptyTypeLiteralType || isValidTypeForTemplateLiteralPlaceholder(source, t)); |
There was a problem hiding this comment.
Why do we need to have t === emptyTypeLiteralType here? Couldn't source not be assignable to {}?
There was a problem hiding this comment.
emptyTypeLiteralType isn't a valid type for a template literal placeholder. Without this, we run into problems with what this PR is fixing:
test failures
diff --git a/tests/baselines/reference/templateLiteralTypesPatterns.errors.txt b/tests/baselines/reference/templateLiteralTypesPatterns.errors.txt
index cd82afc839..7bd15a6f82 100644
--- a/tests/baselines/reference/templateLiteralTypesPatterns.errors.txt
+++ b/tests/baselines/reference/templateLiteralTypesPatterns.errors.txt
@@ -55,10 +55,12 @@ templateLiteralTypesPatterns.ts(129,9): error TS2345: Argument of type '"1.1e-10
templateLiteralTypesPatterns.ts(140,1): error TS2322: Type '`a${string}`' is not assignable to type '`a${number}`'.
templateLiteralTypesPatterns.ts(141,1): error TS2322: Type '"bno"' is not assignable to type '`a${any}`'.
templateLiteralTypesPatterns.ts(160,7): error TS2322: Type '"anything"' is not assignable to type '`${number} ${number}`'.
+templateLiteralTypesPatterns.ts(205,16): error TS2345: Argument of type '"testDowncast"' is not assignable to parameter of type '`${string & {}}Downcast` | "downcast" | "dataDowncast" | "editingDowncast"'.
+templateLiteralTypesPatterns.ts(207,17): error TS2345: Argument of type '"testDowncast"' is not assignable to parameter of type '"downcast" | "dataDowncast" | "editingDowncast" | `${{} & string}Downcast`'.
templateLiteralTypesPatterns.ts(211,5): error TS2345: Argument of type '"abcTest"' is not assignable to parameter of type '`${`a${string}` & `${string}a`}Test`'.
-==== templateLiteralTypesPatterns.ts (58 errors) ====
+==== templateLiteralTypesPatterns.ts (60 errors) ====
type RequiresLeadingSlash = `/${string}`;
// ok
@@ -378,8 +380,12 @@ templateLiteralTypesPatterns.ts(211,5): error TS2345: Argument of type '"abcTest
// repro from https://github.com/microsoft/TypeScript/issues/54177#issuecomment-1538436654
function conversionTest(groupName: | "downcast" | "dataDowncast" | "editingDowncast" | `${string & {}}Downcast`) {}
conversionTest("testDowncast");
+ ~~~~~~~~~~~~~~
+!!! error TS2345: Argument of type '"testDowncast"' is not assignable to parameter of type '`${string & {}}Downcast` | "downcast" | "dataDowncast" | "editingDowncast"'.
function conversionTest2(groupName: | "downcast" | "dataDowncast" | "editingDowncast" | `${{} & string}Downcast`) {}
conversionTest2("testDowncast");
+ ~~~~~~~~~~~~~~
+!!! error TS2345: Argument of type '"testDowncast"' is not assignable to parameter of type '"downcast" | "dataDowncast" | "editingDowncast" | `${{} & string}Downcast`'.
function foo(str: `${`a${string}` & `${string}a`}Test`) {}
foo("abaTest"); // okThis was really meant to be a "faster"/more concise version of:
if (target.flags & TypeFlags.Intersection) {
if (areIntersectedTypesAvoidingPrimitiveReduction((target as IntersectionType).types)) {
const primitive = (target as IntersectionType).types[0] === emptyTypeLiteralType ? (target as IntersectionType).types[1] : (target as IntersectionType).types[0];
return isValidTypeForTemplateLiteralPlaceholder(source, primitive);
}
return every((target as IntersectionType).types, t => isValidTypeForTemplateLiteralPlaceholder(source, t));
}Couldn't source not be assignable to {}?
This is a good question. I've tried to end up with such a source and I couldn't figure out a way to hit this. The whole existing test suite also doesn't hit such a case. I won't swear that it's impossible though so maybe it's better to use this alternative version that I posted above?
There was a problem hiding this comment.
Ok, I looked at the code some more and I think this is actually ok (but like you said, I can't prove it's impossible).
|
@gabritto Here they are:
CompilerComparison Report - main..54188
System
Hosts
Scenarios
TSServerComparison Report - main..54188
System
Hosts
Scenarios
StartupComparison Report - main..54188
System
Hosts
Scenarios
Developer Information: |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@gabritto Here are the results of running the top-repos suite comparing Everything looks good! |
|
@gabritto Here are the results of running the top-repos suite comparing Something interesting changed - please have a look. DetailsServer exited prematurely with code unknown and signal SIGABRTAffected reposcalcom/cal.comRaw error text:RepoResults4/calcom.cal.com.rawError.txt in the artifact folder
Last few requests{"seq":864,"type":"request","command":"updateOpen","arguments":{"changedFiles":[],"closedFiles":[],"openFiles":[{"file":"@PROJECT_ROOT@/apps/swagger/pages/_app.tsx","projectRootPath":"@PROJECT_ROOT@"}]}}
{"seq":865,"type":"request","command":"getOutliningSpans","arguments":{"file":"@PROJECT_ROOT@/apps/swagger/pages/_app.tsx"}}
{"seq":866,"type":"request","command":"updateOpen","arguments":{"changedFiles":[],"closedFiles":["@PROJECT_ROOT@/apps/storybook/components/Title.tsx"],"openFiles":[]}}
{"seq":867,"type":"request","command":"updateOpen","arguments":{"changedFiles":[],"closedFiles":[],"openFiles":[{"file":"@PROJECT_ROOT@/apps/web/components/apps/App.tsx","projectRootPath":"@PROJECT_ROOT@"}]}}
Repro steps
|
|
Hey @gabritto, the results of running the DT tests are ready. |
|
It looks like this PR caused an out of memory error on a repo: #54188 (comment) |
|
@gabritto I'm not sure if this failure is related to this PR. I can repro it but I can repro it using the build from |
|
@typescript-bot test tsserver top100 |
|
Heya @gabritto, I've started to run the diff-based top-repos suite (tsserver) on this PR at f5f1403. You can monitor the build here. Update: The results are in! |
I might have misinterpreted the results in the rush. I can't repro this with either build (from this PR and from the main). Now I'm interested if the CI job will be able to repro it again 😅 |
|
@gabritto Here are the results of running the top-repos suite comparing Everything looks good! |
|
Seems like CI is fine now? I think this looks good for 5.3. |
fixes #54177 (comment)