Skip to content

tsc crashes with typescript@>4.0.0 #40239

Closed

Description

@anilanar

TypeScript Version: 4.1.0-dev.20200824

Search Terms: tsc cannot read property 'length' of undefined getResolvedMembersOrExportsOfSymbol symbol.declarations

Problem
tsc crashes after upgrading from 3.9.6 to 4.x.

Code

This problem happens after upgrading typescript on a project with 100k lines of code.
I don't have reproduction but I did my best to figure out what might be going wrong.

The crash stack trace:

TypeError: Cannot read property 'length' of undefined
    at getResolvedMembersOrExportsOfSymbol (/home/aanar/Development/Javascript/projects/Userlike/apps/umf/node_modules/typescript/lib/tsc.js:41835:68)
    at getMembersOfSymbol (/home/aanar/Development/Javascript/projects/Userlike/apps/umf/node_modules/typescript/lib/tsc.js:41868:19)
    at isEmptyAnonymousObjectType (/home/aanar/Development/Javascript/projects/Userlike/apps/umf/node_modules/typescript/lib/tsc.js:46924:60)
    at addTypeToIntersection (/home/aanar/Development/Javascript/projects/Userlike/apps/umf/node_modules/typescript/lib/tsc.js:44587:17)
    at addTypesToIntersection (/home/aanar/Development/Javascript/projects/Userlike/apps/umf/node_modules/typescript/lib/tsc.js:44611:28)
    at getIntersectionType (/home/aanar/Development/Javascript/projects/Userlike/apps/umf/node_modules/typescript/lib/tsc.js:44700:28)
    at instantiateTypeWorker (/home/aanar/Development/Javascript/projects/Userlike/apps/umf/node_modules/typescript/lib/tsc.js:46192:25)
    at instantiateType (/home/aanar/Development/Javascript/projects/Userlike/apps/umf/node_modules/typescript/lib/tsc.js:46166:26)
    at getReturnTypeOfSignature (/home/aanar/Development/Javascript/projects/Userlike/apps/umf/node_modules/typescript/lib/tsc.js:43416:47)
    at checkCallExpression (/home/aanar/Development/Javascript/projects/Userlike/apps/umf/node_modules/typescript/lib/tsc.js:56186:30)

So the crash happens in the first line of the following for loop, while trying to iterate symbol.declarations which is undefined:

  for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) {
      var decl = _a[_i];
      var members = ts.getMembersOfDeclaration(decl);
      if (members) {
          for (var _b = 0, members_5 = members; _b < members_5.length; _b++) {
              var member = members_5[_b];
              if (isStatic === ts.hasStaticModifier(member) && hasLateBindableName(member)) {
                  lateBindMember(symbol, earlySymbols, lateSymbols, member);
              }
          }
      }
  }

I modified tsc.js to place some console.log statements. Right before the line that causes the crash:

  if (!symbol.declarations) {
    console.log(symbol);
  }

The result:

Symbol {
  flags: 33556480,
  escapedName: '__type',
  declarations: undefined,
  valueDeclaration: undefined,
  id: undefined,
  mergeId: undefined,
  parent: undefined,
  checkFlags: 0,
  type: Type {
    flags: 524288,
    id: 107,
    objectFlags: 16,
    symbol: [Circular *1],
    members: Map(1) { 'default' => [Symbol] },
    properties: [ [Symbol] ],
    callSignatures: [],
    constructSignatures: [],
    stringIndexInfo: undefined,
    numberIndexInfo: undefined
  },
  resolvedMembers: Map(0) {}
}

If I console.log(symbol.type.propertires) or symbol.type.members, I notice that it's pointing to @types/react-redux/index.d.ts.

It looks like it works when the for loop for symbol.declarations is wrapped with an if condition as below:

// The crash is due to `symbol.declarations` being undefined. So my naive workaround:
if (symbol.declarations) {
  for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) {
      var decl = _a[_i];
      var members = ts.getMembersOfDeclaration(decl);
      if (members) {
          for (var _b = 0, members_5 = members; _b < members_5.length; _b++) {
              var member = members_5[_b];
              if (isStatic === ts.hasStaticModifier(member) && hasLateBindableName(member)) {
                  lateBindMember(symbol, earlySymbols, lateSymbols, member);
              }
          }
      }
  }
}

If there's anything more I can help with, please let me know.

Activity

  1. RyanCavanaugh commented on Aug 25, 2020

    @RyanCavanaugh
    Member

    Thanks for the debugging on this!

  2. anilanar commented on Aug 25, 2020

    @anilanar
    ContributorAuthor

    Edit: Nevermind, I can reproduce this in dozens of other places.

    Well, after some digging with try/catch and ts.getSourceFileOfNode, I figured out the file that causes it and created minimal (to my knowledge) reproduction.

    It seems it has something to do with dynamic import and esModuleInterop.

    Reproduction: https://github.com/anilanar/tscbug

    "esModuleInterop": true stops the crashing.

  3. sandersn commented on Aug 25, 2020

    @sandersn
    Member

    Here's a standalone repro:

    // @esModuleInterop: true
    // @file:empty-export.d.ts
    export {}
    // @file:index.ts
    declare function mock<M>(_: M): {} & M;
    mock(await import('./empty-export'))

    Edit: For me, I had to turn ON esModuleInterop. Here's the command line I'm using:

    tsc --noemit --skiplibcheck --strict --esModuleInterop ~/src/test/index.ts

    This was true for the tscbug repo as well.

  4. sandersn commented on Aug 25, 2020

    @sandersn
    Member

    The type is the shim type created for a module by esModuleInterop. It has an export named 'default' that's an alias for the empty-export module. However, the shim type's symbol has no declarations, is missing a bunch of other properties, but is marked with TypeLiteral flags (among others). I don't know what to make of it.

    I'm not sure whether the shim type's symbol shouldn't be used anywhere, or whether the mapped type instantiation should be dereferencing or ignoring the shim, or whether the shim needs to better stand in for a real type/symbol. Wesley Wigham (@weswigham) any ideas?

  5. sandersn commented on Aug 25, 2020

    @sandersn
    Member

    PR that introduces this crash is #38673
    Anders Hejlsberg (@ahejlsberg)

  6. weswigham commented on Aug 25, 2020

    @weswigham
    Member

    but is marked with TypeLiteral flags (among others)

    Iirc, its marked as a literal because module objects get marked at literals so they can have inferred index signatures during assignment (since they're immutable). Honestly we should probably just err on the side of being better at handling a symbol without declarations more gracefully (the esmodule synthetic symbol is far from the only one without a declaration).

  7. artaommahe commented on Sep 8, 2020

    @artaommahe

    When new version with this fix will be released? Faced this crash while upgrading monorepo with angular projects to ng10 and ts 4.0.2..

  8. JackCA commented on Sep 24, 2020

    @JackCA

    And FWIW, I'm still getting this on v4.0.3

  9. anilanar commented on Sep 24, 2020

    @anilanar
    ContributorAuthor

    Maksim Popov (@artaommahe) ᒍ ᗩ ᑕ K (@JackCA) Please try beta which is prerelease 4.1.0.

  10. JackCA commented on Oct 7, 2020

    @JackCA
  11. artaommahe commented on Oct 7, 2020

    @artaommahe

    Anıl Anar (@anilanar) cant use 4.1.x cause angular-cli 10.1.x does not support it. Also this issue marked as fixed by 4.0.3 (https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&q=milestone%3A%22TypeScript+4.0.3%22+is%3Aclosed+) but it's not, still crashing 😕

  12. zaunermax commented on Nov 4, 2020

    @zaunermax

    Maybe the info is relevant, but i also ran into this by adding the resolveJsonModule flag to the compile options and dynamically importing some JSON. Upgrading to Typescript 4.1.0-beta solved the issue 👍

  13. locked as resolved and limited conversation to collaborators on Oct 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

BugA bug in TypeScriptFix AvailableA PR has been opened for this issue

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions