Repository navigation
Hex String - Expression produces a union type that is too complex to represent. #43388
Description
Bug Report
I recently ran into this type error. I understand that there are cases where reducing the complexity of a union can be challenging, however in this particular case...I do wonder if it actually is really too complex, given the repetitive nature of the type.
Using the new TS v4 Template Literal types, I have tried to create a type for a MongoDB ObjectId. I started out quite basic:
type Hex = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f';
export type ObjectId = `${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}`;This spit back the too complex to represent error. I then wondered if I transitioned some of the complexity from the template literal type to the union, if that might make a difference:
type Hex =
'00' | '01' | '02' | '03' | '04' | '05' | '06' | '07' | '08' | '09' | '0a' | '0b' | '0c' | '0d' | '0e' | '0f' |
'10' | '11' | '12' | '13' | '14' | '15' | '16' | '17' | '18' | '19' | '1a' | '1b' | '1c' | '1d' | '1e' | '1f' |
'20' | '21' | '22' | '23' | '24' | '25' | '26' | '27' | '28' | '29' | '2a' | '2b' | '2c' | '2d' | '2e' | '2f' |
'30' | '31' | '32' | '33' | '34' | '35' | '36' | '37' | '38' | '39' | '3a' | '3b' | '3c' | '3d' | '3e' | '3f' |
'40' | '41' | '42' | '43' | '44' | '45' | '46' | '47' | '48' | '49' | '4a' | '4b' | '4c' | '4d' | '4e' | '4f' |
'50' | '51' | '52' | '53' | '54' | '55' | '56' | '57' | '58' | '59' | '5a' | '5b' | '5c' | '5d' | '5e' | '5f' |
'60' | '61' | '62' | '63' | '64' | '65' | '66' | '67' | '68' | '69' | '6a' | '6b' | '6c' | '6d' | '6e' | '6f' |
'70' | '71' | '72' | '73' | '74' | '75' | '76' | '77' | '78' | '79' | '7a' | '7b' | '7c' | '7d' | '7e' | '7f' |
'80' | '81' | '82' | '83' | '84' | '85' | '86' | '87' | '88' | '89' | '8a' | '8b' | '8c' | '8d' | '8e' | '8f' |
'90' | '91' | '92' | '93' | '94' | '95' | '96' | '97' | '98' | '99' | '9a' | '9b' | '9c' | '9d' | '9e' | '9f' |
'a0' | 'a1' | 'a2' | 'a3' | 'a4' | 'a5' | 'a6' | 'a7' | 'a8' | 'a9' | 'aa' | 'ab' | 'ac' | 'ad' | 'ae' | 'af' |
'b0' | 'b1' | 'b2' | 'b3' | 'b4' | 'b5' | 'b6' | 'b7' | 'b8' | 'b9' | 'ba' | 'bb' | 'bc' | 'bd' | 'be' | 'bf' |
'c0' | 'c1' | 'c2' | 'c3' | 'c4' | 'c5' | 'c6' | 'c7' | 'c8' | 'c9' | 'ca' | 'cb' | 'cc' | 'cd' | 'ce' | 'cf' |
'd0' | 'd1' | 'd2' | 'd3' | 'd4' | 'd5' | 'd6' | 'd7' | 'd8' | 'd9' | 'da' | 'db' | 'dc' | 'dd' | 'de' | 'df' |
'e0' | 'e1' | 'e2' | 'e3' | 'e4' | 'e5' | 'e6' | 'e7' | 'e8' | 'e9' | 'ea' | 'eb' | 'ec' | 'ed' | 'ee' | 'ef' |
'f0' | 'f1' | 'f2' | 'f3' | 'f4' | 'f5' | 'f6' | 'f7' | 'f8' | 'f9' | 'fa' | 'fb' | 'fc' | 'fd' | 'fe' | 'ff' ;
export type ObjectId = `${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}`;Sadly, this did not help. While TypeScript did not complain about the Hex union, it still complained about the template literal. The highly repetitive nature of the type makes me think it should be possible to reduce the complexity to something that actually could be represented.
🔎 Search Terms
"Expression produces a union type that is too complex to represent."
🕗 Version & Regression Information
- This occurs in 4.x
⏯ Playground Link
💻 Code
type Hex = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f';
export type ObjectId = `${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}${Hex}`;🙁 Actual behavior
TypeScript was unable to represent the ObjectId type due to a union that was too complex.
🙂 Expected behavior
TypeScript should be able to handle initially complex unions if the parts of that union are very repetitive... (?)
Activity
jrista commentedon Mar 26, 2021
Another example, just tried: A 16-digit credit card number:
Interestingly, if I shorten it to this:
It does not complain.
MartinJohns commentedon Mar 26, 2021
Duplicate of #43283 / #40803 and many others. Another relevant issue that is essentially the same as yours: #43335
Gvien that this feature didn't even exist in TypeScript 3.x, I'm really not sure why you would say this changed between these versions.
jrista commentedon Mar 26, 2021
I wouldn't say it is a duplicate of the first two. They both use more complex type structures. I still think there is a legitimate question in why it is not possible to reduce such a repetitive type to something that can be properly represented.
MartinJohns commentedon Mar 26, 2021
That's probably why the TypeScript team didn't close #43335, which definitely is a duplicate of this. Right now it's not working because the feature was simply never intended for something like this, that's why it builds up on union types which have the hard limit.
typescript-bot commentedon Mar 28, 2021
This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.