Bug: Circular references not allowed for template literal types
See original GitHub issueBug Report
🔎 Search Terms
- circularly, template literal
Related issues: #43335.
🕗 Version & Regression Information
- This changed between versions 4.0.5 and 4.1.5 (different bug before)
⏯ Playground Link
Playground link with relevant code
💻 Code
// you can have circular references in tuple types
type OneOrMoreArr0<C> = C | [C, ...OneOrMoreArr0<C>[]];
// note that
//
// type OneOrMoreArr0<C> = C | [C, OneOrMoreArr0<C>];
//
// is also valid
type OneOrMoreArr<C> = Exclude<OneOrMoreArr0<C>, C>;
const noEmptyArr: [] extends OneOrMoreArr<'*'> ? false : true = true;
const x1: OneOrMoreArr<'*'> = ['*'];
const x2: OneOrMoreArr<'*'> = ['*', '*'];
const x3: OneOrMoreArr<'*'> = ['*', '*', '*']
// but when you try and do the same thing with template literal types, you get an error
//
// "Type alias 'OneOrMoreStr0' circularly references itself."
//
// "Type 'OneOrMoreStr0' is not generic."
type OneOrMoreStr0<C extends string> = C | `${C}${OneOrMoreStr0<C>}`
// we should be able to do the above, and then have e.g.,
//
// const y1: OneOrMoreStr<'*'> = '*';
// const y2: OneOrMoreStr<'*'> = '**';
// const y3: OneOrMoreStr<'*'> = '***';
// if 'C' is the empty string, the above just reduces to:
//
// OneOrMoreStr0<''> = '';
//
// otherwise the same logic as with `OneOrMoreArr0` should apply
🙁 Actual behavior
You get the error:
Type alias 'OneOrMoreStr0' circularly references itself.
Type 'OneOrMoreStr0' is not generic.
🙂 Expected behavior
This should type check like with the tuple example - it’s the same principle, just with template literals.
Issue Analytics
- State:
- Created 2 years ago
- Reactions:7
- Comments:11 (4 by maintainers)
Top Results From Across the Web
Typescript template literal types circular constraint
I cannot reference P in the template literal since it creates a circular constraint. Another way might be to reference "original" P, but...
Read more >Invalid template errors - Azure Resource Manager
This article describes how to resolve invalid template errors for Bicep files and Azure Resource Manager templates (ARM templates). The error ...
Read more >Circular reference in Excel: how to find, enable, use, or remove
If circular references are not allowed in your Excel (and they are turned off by default), you will see an error message we've...
Read more >TypeError: cyclic object value - JavaScript - MDN Web Docs
To serialize circular references you can use a library that supports them (e.g. cycle.js) or implement a solution by yourself, ...
Read more >References - FHIR v5.0.0-snapshot3
Resources contain two types of references to other resources: ... identifier · Σ, 0..1, Identifier, Logical reference, when literal reference is not known....
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
I’m honestly not enough of an expert on how we deal with deferred recursive types to be 100% confident about how difficult this would be and what the biggest challenges would be, but I’m familiar enough to have an intuition that it would be complicated. Even if I were wrong about that, I think we’d want to see compelling use cases for why we should add this kind of complexity. Template literal types were created in large part to support mapped type
as
clauses, which have super compelling uses, like describing the relationship between an object like{ foo: string }
and{ getFoo(): string, setFoo(foo: string): void }
. I don’t think a super-fine-grained type-space string validator is as compelling as that, but that’s why issues like this one are Awaiting More Feedback.Yes 😄