Microsoft/TypeScript

Undetected illegal assignment of nested array types

Open

#52.912 geöffnet am 22. Feb. 2023

Auf GitHub ansehen
 (3 Kommentare) (3 Reaktionen) (0 zugewiesene Personen)TypeScript (6.726 Forks)batch import
BugCursed?Domain: check: Error InstabilityHelp Wanted

Repository-Metriken

Stars
 (48.455 Stars)
PR-Merge-Metriken
 (Durchschn. Merge 6T 17h) (9 gemergte PRs in 30 T)

Beschreibung

Bug Report

Typescript does not allow the assignment of Source4 to Target4 which is expected because they are incompatible. After 3 or more levels of nested array properties this error is not detected anymore. Even the errors on the nested types may disappear depending on the order of the assignments.

Note: every type is explicitly named and there are no cycles.

(This actually caused problems in our production codebase)

🔎 Search Terms

nested array assignment, undetected illegal assignment of nested array types, undetected illegal assignment, illegal assignment

🕗 Version & Regression Information

  • In versions before 4.5.3: limit of nested array levels is 5 instead of 3
  • This changed between versions 4.4.4 and 4.5.3 (to 3 levels)
  • PRs:
    • bisect: #46974 (thank you @pyBlob for bisect)
    • main: #46599
      • maybe: isDeeplyNestedType maxDepth check?

⏯ Playground Link

Playground link with relevant code

💻 Code

type Source1 = { array: Source2[] };
type Source2 = { array: Source3[] };
type Source3 = { array: Source4[] };
type Source4 = {};

// same as Source types but with "someNewProperty"
type Target1 = {
  array: Target2[];
  // someNewProperty: string // error in target1 assignment as expected if enabled
};
type Target2 = {
  array: Target3[];
  // someNewProperty: string // error in target1 assignment as expected if enabled
};
type Target3 = {
  array: Target4[];
  // someNewProperty: string // error in target1 assignment as expected if enabled
};
type Target4 = {
  someNewProperty: string; // not existing in Source4 => no error in target1 assignment
};

declare const source1: Source1;
declare const source2: Source2;
declare const source3: Source3;
declare const source4: Source4;

// this should not compile:
const target1: Target1 = source1; // comment this line to get errors in target2, target3 assignments or move this line after target2 assignment

// this should not compile:
const target2: Target2 = source2; // error if target1 assignment is commented or after this assignment

// this should not compile:
const target3: Target3 = source3; // error if target1 assignment is commented or after target2 assignment

// does not compile:
const target4: Target4 = source4; // error as expected

/*
PS:
- same (wrong) behavior with interfaces and classes
*/

🙁 Actual behavior

  • Source1 is assignable to Target1
  • Source2 is assignable to Target2
  • Source3 is assignable to Target3
  • Reordering of assignments impact type checking
    • If source1 assignment is skipped or moved after source2 assignment the expected errors show

🙂 Expected behavior

  • Source1 is not assignable to Target1
Type 'Source1' is not assignable to type 'Target1'.
  Types of property 'array' are incompatible.
    Type 'Source2[]' is not assignable to type 'Target2[]'.
      Type 'Source2' is not assignable to type 'Target2'.
        Types of property 'array' are incompatible.
          Type 'Source3[]' is not assignable to type 'Target3[]'.
            Type 'Source3' is not assignable to type 'Target3'.
              Types of property 'array' are incompatible.
                Type 'Source4[]' is not assignable to type 'Target4[]'.
                  Property 'someNewProperty' is missing in type 'Source4' but required in type 'Target4'.
  • Since Source1 is a fixed/static tree (without any self references) I expect the error to be found by the compiler.
  • Reordering of assignments do not impact type checking results

Related issues

https://github.com/microsoft/TypeScript/issues/42070

Contributor Guide