Microsoft/TypeScript

Conditional type eagerly calculated to be invariant breaks referential transparency

Open

#62.798 aberto em 23 de nov. de 2025

Ver no GitHub
 (4 comments) (0 reactions) (0 assignees)TypeScript (6.726 forks)batch import
BugCursed?Domain: check: Variance RelationshipsHelp Wanted

Métricas do repositório

Stars
 (48.455 stars)
Métricas de merge de PR
 (Mesclagem média 6d 17h) (9 fundiu PRs em 30d)

Description

🔎 Search Terms

Conditional types, Invariance, Referential transparency

🕗 Version & Regression Information

Tried with v5.9.3

⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.9.3#code/C4TwDgpgBAYgPAFQHxQLxQN5QG4EMA2ArhAFxQJQQAewEAdgCYDOUA9gEYBWEAxsFAH4oAawghWAM3JQyFAL4AoBaEhQASgEY0sOBjkpqtRi3hZcZJsABOASzoBzKPsFQARAAtW+Zq5luGrBAsdKz8nt6uCgD0UVBxAHoCSirQMLjapvrK4KnsGbpQ5lCWtg5OSMk56gBMGemG9MyweUIeXj5+rgFBUCFh7ZExcVCJCkA

💻 Code

type F<T> = { value: T extends object ? keyof T : T }

type R1 = F<{}> extends F<{ a: string }> ? "holds" : "does not hold"
//   ^? "does not hold"

type Fa = F<{}>
type Fb = F<{ a: string }>

type R2 = Fa extends Fb ? "holds" : "does not hold"
//   ^? "holds"

🙁 Actual behavior

R1 computes to "does not hold"

🙂 Expected behavior

R1 computes to "holds"

Additional information about the issue

I'm assuming typescript eagerly calculates F to be invariant and then instead of checking the subtype relation on resolved types it calculates subtype relation of the parameters to F. (This would perhaps have made sense if F was explicitly annotated with in out T.)

Guia do colaborador