Microsoft/TypeScript

Undetected illegal assignment of nested array types

Open

#52,912 创建于 2023年2月22日

在 GitHub 查看
 (3 评论) (3 反应) (0 负责人)TypeScript (6,726 fork)batch import
BugCursed?Domain: check: Error InstabilityHelp Wanted

仓库指标

Star
 (48,455 star)
PR 合并指标
 (平均合并 6天 17小时) (30 天内合并 9 个 PR)

描述

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

贡献者指南