-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Allow intersections to be used as valid types for template literal placeholders #54188
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 OK Some 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
|
@@ -24312,12 +24320,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { | |||
if (source === target || target.flags & (TypeFlags.Any | TypeFlags.String)) { | |||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to have t === emptyTypeLiteralType
here? Couldn't source
not be assignable to {}
?
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.
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"); // ok
This 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 SIGABRT
Affected 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)