Skip to content

Conversation

@eL1fe
Copy link

@eL1fe eL1fe commented Dec 30, 2025

Summary

This PR adds a failing test case for issue #60453.

Bug: Variance is incorrectly computed as Independent (instead of Covariant) for type aliases with deeply nested anonymous object types containing Arrays. This causes type-unsafe assignments to be silently allowed.

Investigation Findings

Reproduction

type DataTypeThree<T extends number | boolean> = {
  one: Array<{ two: Array<{ three: Array<T> }> }>;
};

let a: DataTypeThree<number> = { one: [{ two: [{ three: [5] }] }] };
let b: DataTypeThree<boolean> = a;  // No error! Should error.

Root Cause Analysis

  1. Variance Computation: In getVariancesWorker (checker.ts:24958), variance is computed by comparing Type<markerSubType> vs Type<markerSuperType> using isTypeAssignableTo.

  2. The Problem: For deeply nested types, both comparisons incorrectly return true:

    • isTypeAssignableTo(Sub, Super) = true (correct → Covariant)
    • isTypeAssignableTo(Super, Sub) = true (INCORRECT → adds Contravariant)

    This results in Bivariant variance, which then becomes Independent after the subsequent check.

  3. Cache Evidence: After comparison, the relation cache shows:

    • Without "warmup": SuperToSub = 1 (Succeeded) — wrong!
    • With "warmup": SuperToSub = 2 (Failed) — correct
  4. Order Dependency: The bug manifests only when the complex type is used first. If a simpler generic type with object structure (e.g., type Y<T> = { x: Array<T> }) is used before the complex type, the bug disappears.

  5. Potential Cause: checkTypeRelatedTo returns result !== Ternary.False (line 22404). This means Ternary.Unknown (value 1) is treated as true. When structural comparison encounters edge cases during first use, Unknown may be incorrectly interpreted as success.

Workaround

Explicit variance annotation fixes the issue:

type DataTypeThreeFixed<out T extends number | boolean> = {
  one: Array<{ two: Array<{ three: Array<T> }> }>;
};

Test Plan

  • Add failing test case varianceNestedGenericTypeAlias.ts
  • Fix the variance computation (future PR)
  • Update baselines

Fixes #60453

…iases (microsoft#60453)

This test demonstrates incorrect variance computation for type aliases
with deeply nested anonymous object types containing Arrays.

The variance is incorrectly measured as Independent (meaning the type
parameter is not used) instead of Covariant, causing type-unsafe
assignments to be allowed.
@github-project-automation github-project-automation bot moved this to Not started in PR Backlog Dec 30, 2025
@typescript-bot typescript-bot added the For Backlog Bug PRs that fix a backlog bug label Dec 30, 2025
@eL1fe
Copy link
Author

eL1fe commented Dec 30, 2025

@microsoft-github-policy-service agree

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

For Backlog Bug PRs that fix a backlog bug

Projects

Status: Not started

Development

Successfully merging this pull request may close these issues.

Error not generated for nested generic array

2 participants