Skip to content
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

Type alias circularly references itself (5.4 regression) #58302

Closed
ShacharHarshuv opened this issue Apr 24, 2024 · 3 comments
Closed

Type alias circularly references itself (5.4 regression) #58302

ShacharHarshuv opened this issue Apr 24, 2024 · 3 comments
Assignees
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed

Comments

@ShacharHarshuv
Copy link

πŸ”Ž Search Terms

Type alias circularly references itself (5.4 regression)

πŸ•— Version & Regression Information

  • This changed between versions 5.3.3 and 5.4.5

⏯ Playground Link

https://www.typescriptlang.org/play?ts=5.4.5#code/C4TwDgpgBAQg9nANhAhgOwAouACwM4A8AKgHxQC8UewATgJZoDmUAZALABQUUA3p99wDaAaSgMoAawgg4AMyhEAugC4FIxVAgAPYBDQATPFABGCZOn4DuAfijDLV1UXWadew1DjGAVhADGwA4CtqLaugZGaACuALbGEDRQAD5UtAyMQVa2AAYAJDzCAL4AdPnwSKiY2PjE6iSF2ZkCqmgQAG4JTS3tCQDcloWCUjLySv0c-EA

πŸ’» Code

type BooleanPaths<T> = string &
  {
    [K in keyof T]: T[K] extends boolean
      ? K
      : T[K] extends object
      ? K extends number | string
        ? `${K}.${BooleanPaths<T[K]>}`
        : never
      : never;
  }[keyof T];

πŸ™ Actual behavior

This code fails with two errors:

Type alias 'BooleanPaths' circularly references itself.
Type 'BooleanPaths' is not generic.

πŸ™‚ Expected behavior

The compilation should pass, as it has in previous versions.

Additional information about the issue

No response

@RyanCavanaugh
Copy link
Member

Bisects to #56515

@RyanCavanaugh RyanCavanaugh added the Needs Investigation This issue needs a team member to investigate its status. label Apr 24, 2024
@ahejlsberg
Copy link
Member

The issue is that following #56515 we perform constraint reduction on intersection types T & P or P & T, where T is a type parameter or indexed access type and P is a primitive type, the object type, or {}, reducing the intersection type to just T when the constraint of T fully encompasses P. For example, for a T extends string, the intersection T & string is reduced to just T. In the repro, we attempt to reduce the intersection string & {...}[keyof T], but resolving the constraint of {...}[keyof T] causes a circularity. It's unfortunate, but the price we have to pay to get the benefits of the feature.

I'd suggest rewriting the BooleanPaths type to this simpler formulation:

type BooleanPaths<T, K extends keyof T = keyof T> =
    K extends string ?
      T[K] extends boolean ? K :
      T[K] extends object ? `${K}.${BooleanPaths<T[K]>}` :
      never :
    never;

No circularity and handles both object and tuple types.

@ahejlsberg ahejlsberg added Design Limitation Constraints of the existing architecture prevent this from being fixed and removed Needs Investigation This issue needs a team member to investigate its status. labels May 6, 2024
@typescript-bot
Copy link
Collaborator

This issue has been marked as "Design Limitation" and has seen no recent activity. It has been automatically closed for house-keeping purposes.

@typescript-bot typescript-bot closed this as not planned Won't fix, can't repro, duplicate, stale May 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed
Projects
None yet
Development

No branches or pull requests

4 participants