microsoft / microsoft/TypeScript
Resolution order dependent circular heritage
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 111k
- Forks
- 14.3k
- Avg merge
- 2d 4h
- Merged PRs (30d)
- 132
Description
### 🔎 Search Terms
resolution order dependent circular heritage, circular base type, circular mixin
### 🕗 Version & Regression Information
- This changed in #39675
However, it appears this PR was the first time that circular heritage was (consistently) reported. Therefore this issue has essentially always existed.
### ⏯ Playground Link
https://www.typescriptlang.org/play/?#code/PTAEDEEsA8FMBNSQGagJ4HsCuoDGGBbA2AOwBdQyALSAZ1ABtITZRsKMAnUWgd0jK4qlDKAAGAQVxkuABQAqAJQBMsMQDoAUPFi4GAQ06t8JWhWgAuUAElTZfSVyx5aAA6wAPGTewMqKTKcCiqwAHwA3JpRIKAAqrQIIjxUGLyUVPocJAxooPqgOu4kOo65GCTi8mJI9CxOtLSGuchc6caQnLhYBpwCaFoxEvTMADRtoMjM+gygRrQYDABuiYvTWKzwGLC1GBQEmWSwnFre7qAAIrBF8LQA8iQe8qGgALx5JGiR2ro9xgYNoACrQA3ppQKBXJwMK4rJdrncHgFIMsAKLIZC6MgAbQARJDoTiALoRTQAXyiOj0hlYJH0xForn0ThshwIoFB4JiUDgiBQ6GwPH4gmE1DoSQcSHIR2QTNgWnBp1Y1gIrgYsGI5EykHKrxsdgcThc7g85wwXQ1ZAAwv9aJbypMAOa46ysokk8nfKlGPA2lnq9lg0CWC5XUg3e4eJGo9GY3H41xuyIerkwRJ8zA4IwEDDLcZiADKWAARka1KAHaQjpBcBDDHTYIdjpoqQCgUElKoPIWSz5dQ40M9YNBDsV6G32cmwNy06gM7N1TnWNRWAXi6XqhWWL0a4zOPXG1oW-QXergp3u6W+x9B8Ow8fWROosxGzLmabzaQrTa7SRHQHOVOqa8rOApCA4FbiIqfiAtIcgdmWMiQT40Ftmenj9qEYiBm2VhQf4sHtiEXwARAQFICBOBgSQEFiHhfoEGh1SIbRyGoCeDHwR4GFYeC7G4ax9FoUmFI-NSPr6K20jIrAaIYtIoBDiONygNakCfu+WAWgAsjAzAABQAEISbAUYyTG0gAJT-hCUIwqAJCaUWRzCZ6vwTFgjhkNqFSqepZqaZ+OnQMwHiBimPLkfyOAMBgGAJBUy54OUZh7s+bCoGIRkJNaEm0BogZZbAOUAopd72bAaR6eo1WGA6tBWP2WKElZLzPBgRYAFaYiMmihIZxlWIVxW0BZg3GcNXyUm5R6gIVpmyZi1kmClWAEVVNWcHVsKhqOEbseoyqquqn5auUoQWUmQA
### 💻 Code
```ts
// Fixed if you comment this line out or switch to `ActorPTR2e`.
declare const x: InstanceType;
// Used to show that only a dependency on `T` is necessary for the circularity.
// As in, the final resolved value does not matter.
type DependsOn = any;
declare class Actor {
prop: DependsOn;
}
declare namespace Item {
// Fixed if you switch this to an interface.
type Implementation = InstanceType;
}
declare class Item {
x: DependsOn;
}
// Fixed if you remove the `SubType` generic parameter.
class ActorPTR2e extends Actor {}
// Fixed if you remove the `SubType` generic parameter.
class ItemPTR2e extends Item {}
interface DocumentClassConfig {
// Fixed if you change `typeof ActorPTR2e` to `typeof ActorPTR2e`
Actor: typeof ActorPTR2e;
// Fixed if you change `typeof ItemPTR2e` to `typeof ItemPTR2e`
Item: typeof ItemPTR2e;
}
declare class ActiveEffect extends ClientDocumentMixin(BaseActiveEffect) {
prop: number;
}
declare function ClientDocumentMixin<
// Fixed if you loosen the constraint of `BaseClass`.
BaseClass extends new (...args: any[]) => object,
>(Base: BaseClass): BaseClass;
declare class BaseActiveEffect {
constructor(...args: DependsOn);
}
```
### 🙁 Actual behavior
Numerous errors, namely:
```
Type alias 'Implementation' circularly references itself.
Type 'ActiveEffect' recursively references itself as a base type.
'ActiveEffect' is referenced directly or indirectly in its own base expression.
'args' is referenced directly or indirectly in its own type annotation.
```
### 🙂 Expected behavior
No error, as seen when you comment out the line `declare const x: InstanceType;`. The error going away indicates that this circularity is resolution order dependent.
I understand how odd the code is out of context but I did actually run into this in a real codebase.
### Additional information about the issue
_No response_
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the linked TypeScript Playground reproduction and trace the reported circular type-alias, base-type, and annotation diagnostics around InstanceType, generic class heritage, and mixin constraints. Done means the reproduction no longer reports these resolution-order-dependent errors without changing the example to avoid the circularity.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100