-
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
Inferring a key within a string inconsistently yields too wide a union #57126
Comments
This is a somewhat confusing behavior but it works as expected. The algorithm first infers something - a single character: type WithConstraintUsed = 'aaXXX' extends `${keyof D1 & string}${string}` ? keyof D1 & string : false
// ^? type WithConstraintUsed = "aa" | "b" | "c" This is quite confusing because it makes the more concise/intuitive variant worse than the verbose one (one that behaves like you have expected): type Test<Data, T> = T extends `${infer K}${string}`
? K extends keyof Data & string
? K
: false
: false; |
This is effectively the same as #49839 - the constraint of type parameters, including those introduced by |
Is this true just for string matching? Or is it a general rule? I remember I landed a pull request that introduced an implied arity based on those constraints for some variadic elements when inferring from tuples. This has been a while ago - but should such a change be reverted? Or is the context there sufficiently different that this implied arity is OK there? Note that I realized later that this change wasn't perfect - it only handles some cases (it doesn't make other cases worse though). |
Thank you for explaining. @Andarist: I was about to get even more confused imagining the option you mentioned would work the way I'd been expecting. Fortunately (I guess?), it doesn't. Good news is that this provides a way to parse a string one character at a time. |
Ah yes - sorry. Sorry for the confusion - as you mentioned, the proposed version is not good since
I recommend doing this most of the time.
Like here? type Test<T extends string> = T extends `${infer Char}${string}` ? Char : never;
type Result = Test<"">; // never Or did you mean something closer to this? type D2 = {
"": "empty";
};
type Test<Data, T> = T extends `${infer K extends keyof Data & string}${string}`
? K
: false;
type T2 = Test<D2, "">; |
I had the first example in my mind. |
Yeah, this isn't that different. From #40336 :
You have 2 placeholders here so the first one tries to consume a single character - but there is none when you instantiate this One extra quirk related to empty strings that I know of is this one: #49839 (comment) . It's quite similar to your problem here - the inferred |
I was trying to investigate about the behavior we can observe in the example you linked. type Exactly3<T extends string> =
T extends `${any}${any}${any}${infer Last extends ''}` ?
T :
never;
type Exactly3_Infer<T extends string> =
T extends `${infer A}${infer B}${infer C}${infer Last extends ''}` ?
[A, B, C, Last] :
never;
type T = Exactly3<'abcd'>; // 'abcd' ie. the original problem
type T_Infer = Exactly3_Infer<'abcd'>; // never ie. you shall never know what was going on Is it because having found fitting types for A, B and C on the "first run", there is no going back in the back-anchored attempt for Last? Assuming it even takes place since with that in mind, it could fail immediately... |
Not quite. I think it's just because this version "removes" the placeholders - and thus it removes the behavior associated with them.
|
This issue has been marked as "Duplicate" and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
π Search Terms
infer, keyof, string, interpolation, union, all keys, too big, too wide
π Version & Regression Information
Syntax not supported before 4.7
Similar behavior on all versions upwards
β― Playground Link
https://www.typescriptlang.org/play?ts=5.3.3&ssl=6&ssc=1&pln=21&pc=47#code/PTAEEkDsDMFMCd4EtIHNQENQGtYE9QB3JAFwAsVNQBnE5NUFAYwHtJqlbZISAbAvEli8AJtVAkWLIkhGwqAV0hI2AWABQGkDTw8MAD1CQWJGgoAO5lvBKwRoAEaxo1+QBYAdAHYPbrWAcFdGh4FgBbCTIEeTVNdRI8c3kAEQAGUABeUABvDVBMAC5QAHJU4oAaPMci4oBGCqqmGoAmYo0AXwBuDQ0EpNBk2sycqowMGrLK9XyHGvqp-KaS1o7uuL75ABVYWgAeZIwSDHLQTYA+Yc3QWH1bSDFQAAMAEmyUOHhQAGlr2+4H3B4FjQAaHLAAMhodBQqHar1o9Fhj1AAH5vqAitAMLxqLA1r1Elt0lltns0idihgABo04pnTr5fLaSlteKE05DEk7Ej7WoUsY0ql0hlMsDFBzFAA+xSYUspGFZQA
π» Code
π Actual behavior
T1 is the union of all keys of D1 while only one fits within the pattern.
The extra keys are irrelevant.
The inference is not helpful.
This behavior seems inconsistent since T0 gives the expected key.
π Expected behavior
T1 = 'aa'
Additional information about the issue
No response
The text was updated successfully, but these errors were encountered: