Microsoft/TypeScript

False positive for Circular dependency error

Open

#54,204 建立於 2023年5月10日

在 GitHub 查看
 (3 留言) (0 反應) (0 負責人)TypeScript (6,726 fork)batch import
Domain: check: Type CircularityHelp WantedPossible Improvement

倉庫指標

Star
 (48,455 star)
PR 合併指標
 (平均合併 6天 17小時) (30 天內合併 9 個 PR)

描述

Bug Report

Hello. First of all want to express my love to TypeScript and admit of all work you did for the best typing system I've ever known.

I believe I found a bug where three points are touched: type inference, recursive types and variadic params. The bug doesn't happen when you take off any of this points. I put the reproduction code below.

I believe that it's a bug because the main recursive feature works fine for composite that has slightly complicated signature. Also, I can make failing working by making a union with a dummy type, so it's

failing: AComponent<[ARows | 'never']>

The bug doesn't happen when I have the direct components type without infering:

type AComponentTypes = {
  simple: [string],
  composite: [string, ARows]
  failing: [ARows]
}

The bug doesn't happen when I don't use variadic types:

type ARowUnion<U> = U extends keyof AComponents ? [U, AArgument<AComponents[U]>] : never

Is there any other workarounds besides defining a unionARows | 'never' ?

I spent about 4 hours struggling with this so I hope this is a helpful finding. Thank you

🔎 Search Terms

typescript, generic types, variadic types, composition, recursion, self reference, mapped types, false positive

🕗 Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about
  • I was unable to test this on prior versions because variadic types were not implemented.
  • There is no working version. 4.0.5. still has the problem, but 3.9.7 seems not supporting variadic types.

⏯ Playground Link

Playground link with relevant code

💻 Code

type AComponents = {
  simple: AComponent<[string]>,
  composite: AComponent<[string, ARows]>
  failing: AComponent<[ARows]>
}

type AComponent<T extends unknown[]> = (args: T) => void

type AArgument<T> = T extends AComponent<infer V> ? V : never

type ARowUnion<U> = U extends keyof AComponents ? [U, ...AArgument<AComponents[U]>] : never

type ARow = ARowUnion<keyof AComponents>
type ARows = ARow[]

const rows: ARow[] = [
  ['simple', 'Hello world'],
  ['composite', 'my param', [
    ['simple', 'Hello world'],
  ]],
  ['failing', [
    ['simple', 'Hello world'],
  ]]
]

🙁 Actual behavior

Type alias 'ARow' circularly references itself. Type arguments for 'Array' circularly reference themselves.

🙂 Expected behavior

There is no errors for the types definitions, both failing and component types are valid and allows recursive structures.

貢獻者指南