Typescript: TypeError: Cannot read property 'valueDeclaration' of undefined (continuation)

Created on 20 Dec 2019  路  19Comments  路  Source: microsoft/TypeScript

This is a continuation of https://github.com/microsoft/TypeScript/issues/34869

I'm still getting the error testing against v3.8.0-dev.20191205
Here is my stack trace (the first one is react-styleguidist)

Trace
    at withContext (node_modules/typescript/lib/typescript.js:36361:25)
    at Object.typeToTypeNode (node_modules/typescript/lib/typescript.js:36316:28)
    at typeToString (node_modules/typescript/lib/typescript.js:36283:40)
    at Object.typeToString (node_modules/typescript/lib/typescript.js:33355:24)
    at Parser.getDocgenType (node_modules/react-docgen-typescript/lib/parser.js:284:43)
    at node_modules/react-docgen-typescript/lib/parser.js:331:29
    at Array.forEach (<anonymous>)
    at Parser.getPropsInfo (node_modules/react-docgen-typescript/lib/parser.js:309:27)
    at Parser.getComponentInfo (node_modules/react-docgen-typescript/lib/parser.js:129:30)
    at node_modules/react-docgen-typescript/lib/parser.js:702:27
    at Array.map (<anonymous>)
    at node_modules/react-docgen-typescript/lib/parser.js:701:14
    at Array.reduce (<anonymous>)
    at parseWithProgramProvider (node_modules/react-docgen-typescript/lib/parser.js:694:10)
    at parse (node_modules/react-docgen-typescript/lib/parser.js:71:20)
    at Object.module.exports (node_modules/react-styleguidist/lib/loaders/props-loader.js:41:12)
 FAIL  Failed to compile

[internal]
INTERNAL ERROR: Cannot read property 'valueDeclaration' of undefined
stack trace:
TypeError: Cannot read property 'valueDeclaration' of undefined
    at getBaseConstructorTypeOfClass (node_modules/typescript/lib/typescript.js:40026:40)
    at serializeAsClass (node_modules/typescript/lib/typescript.js:38036:42)
    at serializeSymbolWorker (node_modules/typescript/lib/typescript.js:37770:29)
    at serializeSymbol (node_modules/typescript/lib/typescript.js:37711:38)
    at node_modules/typescript/lib/typescript.js:37686:25
    at Map.forEach (<anonymous>)
    at visitSymbolTable (node_modules/typescript/lib/typescript.js:37685:33)
    at symbolTableToDeclarationStatements (node_modules/typescript/lib/typescript.js:37556:17)
    at node_modules/typescript/lib/typescript.js:36340:106
    at withContext (node_modules/typescript/lib/typescript.js:36362:37)
error Command failed with exit code 1.

Related Issues:
https://github.com/microsoft/TypeScript/issues/34869

Bug Rescheduled

Most helpful comment

This was fixed in #38508.

All 19 comments

@evenfrost @arian @BernsteinA @elibarzilay new issue here

@jasonwilliams how do we reproduce the issue?

@RyanCavanaugh thats what a few of us are trying to work out, this is happening on a large private repo which isn鈥檛 useful to you so the best I can provide is a stack trace.

From the last issue we are trying to narrow this down.

I've narrowed down the issue and it appears when using fork-ts-checker-webpack-plugin with webpack. If I remove ForkTsCheckerWebpackPlugin from my webpack plugins list, build runs without errors. It happens both in dev (with webpack-dev-server) and production build (when using webpack right away).

So after 4 hours of digging I've finally tracked down the issue (for me at least).

TL;DR: You should explicitly specify tsconfig option in ForkTsCheckerWebpackPlugin if you're using custom TS config file location.

Long story: I'm using webpack, ts-loader, fork-ts-checker-webpack-plugin and 2 separate TS config files (the one builds the client and is located in {project_root}/client/tsconfig.json, another one builds the server and is located in {project_root/tsconfig.json}). For client build I'm using ForkTsCheckerWebpackPlugin, which apparently has its own tsconfig option to specify custom tsconfig.json file path (which I thought would be inherited from configFile option of ts-loader). As I haven't specified tsconfig, fork-ts-checker-webpack-plugin took the config from {project_root/tsconfig.json}, which was server config, and ts-loader took it from correct location ({project_root}/client/tsconfig.json).

Don't know why it was working on TypeScript 3.6, but 3.7 release became really unhappy with it.

First off Happy New Year, back to debugging this.

@evenfrost explicitly specifying the tsconfig.json location didn't help me, i still get the same error.
However, like you said, removing the ForkTsCheckerWebpackPlugin from the webpack config removes the error.

Update:
I can get a successful build when i set useTypescriptIncrementalApi: false, within ForkTsCheckerWebpackPlugin settings.

Also, i have a better stack trace

TypeError: Cannot read property 'valueDeclaration' of undefined
    at getBaseConstructorTypeOfClass (node_modules/typescript/lib/typescript.js:40017:40)
    at serializeAsClass (node_modules/typescript/lib/typescript.js:38025:42)
    at serializeSymbolWorker (node_modules/typescript/lib/typescript.js:37759:29)
    at serializeSymbol (node_modules/typescript/lib/typescript.js:37700:38)
    at node_modules/typescript/lib/typescript.js:37675:25
    at Map.forEach (<anonymous>)
    at visitSymbolTable (node_modules/typescript/lib/typescript.js:37674:33)
    at symbolTableToDeclarationStatements (node_modules/typescript/lib/typescript.js:37545:17)
    at node_modules/typescript/lib/typescript.js:36342:106
    at withContext (node_modules/typescript/lib/typescript.js:36363:37)
    at Object.symbolTableToDeclarationStatements (node_modules/typescript/lib/typescript.js:36342:28)
    at Object.getDeclarationStatementsForSourceFile (node_modules/typescript/lib/typescript.js:64418:64)
    at transformDeclarationsForJS (node_modules/typescript/lib/typescript.js:88026:35)
    at transformRoot (node_modules/typescript/lib/typescript.js:88103:57)
    at transformation (node_modules/typescript/lib/typescript.js:89306:24)
    at transformRoot (node_modules/typescript/lib/typescript.js:89326:82)
    at Object.map (node_modules/typescript/lib/typescript.js:543:29)
    at Object.transformNodes (node_modules/typescript/lib/typescript.js:89313:30)
    at emitDeclarationFileOrBundle (node_modules/typescript/lib/typescript.js:89891:43)
    at emitSourceFileOrBundle (node_modules/typescript/lib/typescript.js:89800:13)
    at forEachEmittedFile (node_modules/typescript/lib/typescript.js:89552:34)
    at Object.emitFiles (node_modules/typescript/lib/typescript.js:89780:9)
    at emitWorker (node_modules/typescript/lib/typescript.js:95796:33)
    at node_modules/typescript/lib/typescript.js:95757:66
    at runWithCancellationToken (node_modules/typescript/lib/typescript.js:95848:24)
    at Object.emit (node_modules/typescript/lib/typescript.js:95757:20)
    at Object.getFileEmitOutput (node_modules/typescript/lib/typescript.js:97391:34)
    at updateShapeSignature (node_modules/typescript/lib/typescript.js:97637:39)
    at Object.getFilesAffectedBy (node_modules/typescript/lib/typescript.js:97591:18)
    at getNextAffectedFile (node_modules/typescript/lib/typescript.js:98062:51)
    at getSemanticDiagnosticsOfNextAffectedFile (node_modules/typescript/lib/typescript.js:98584:32)
    at Object.getSemanticDiagnostics (node_modules/typescript/lib/typescript.js:98628:20)
    at emitFilesAndReportErrors (node_modules/typescript/lib/typescript.js:99945:54)
    at Object.result.afterProgramCreate (node_modules/typescript/lib/typescript.js:100137:13)
    at CompilerHost.afterProgramCreate (node_modules/fork-ts-checker-webpack-plugin/lib/CompilerHost.js:249:21)
    at synchronizeProgram (node_modules/typescript/lib/typescript.js:100380:22)
    at Object.createWatchProgram (node_modules/typescript/lib/typescript.js:100326:9)
    at CompilerHost.<anonymous> (node_modules/fork-ts-checker-webpack-plugin/lib/CompilerHost.js:76:48)
    at Generator.next (<anonymous>)
    at node_modules/fork-ts-checker-webpack-plugin/lib/CompilerHost.js:7:71
    at new Promise (<anonymous>)
    at __awaiter (node_modules/fork-ts-checker-webpack-plugin/lib/CompilerHost.js:3:12)
    at CompilerHost.processChanges (node_modules/fork-ts-checker-webpack-plugin/lib/CompilerHost.js:64:16)
    at ApiIncrementalChecker.<anonymous> (node_modules/fork-ts-checker-webpack-plugin/lib/ApiIncrementalChecker.js:68:66)
    at Generator.next (<anonymous>)
    at node_modules/fork-ts-checker-webpack-plugin/lib/ApiIncrementalChecker.js:7:71
    at new Promise (<anonymous>)
    at __awaiter (node_modules/fork-ts-checker-webpack-plugin/lib/ApiIncrementalChecker.js:3:12)
    at ApiIncrementalChecker.getDiagnostics (node_modules/fork-ts-checker-webpack-plugin/lib/ApiIncrementalChecker.js:67:16)
    at node_modules/fork-ts-checker-webpack-plugin/lib/service.js:88:41
    at Generator.next (<anonymous>)
    at node_modules/fork-ts-checker-webpack-plugin/lib/service.js:7:71
    at new Promise (<anonymous>)
    at __awaiter (node_modules/fork-ts-checker-webpack-plugin/lib/service.js:3:12)
    at run (node_modules/fork-ts-checker-webpack-plugin/lib/service.js:83:12)
    at Object.run (node_modules/fork-ts-checker-webpack-plugin/lib/service.js:112:7)
    at RpcProvider._handeRpc (node_modules/worker-rpc/lib/RpcProvider.js:106:54)
    at RpcProvider.dispatch (node_modules/worker-rpc/lib/RpcProvider.js:22:29)
    at process.<anonymous> (node_modules/fork-ts-checker-webpack-plugin/lib/service.js:33:38)
    at process.emit (events.js:210:5)
    at emit (internal/child_process.js:878:12)
    at processTicksAndRejections (internal/process/task_queues.js:81:21)

Using

I've ran git bisect against commits between v3.6.4 (where it works) and v3.7-rc (where it fails).

The offending commit seems to be this one
https://github.com/microsoft/TypeScript/commit/29becf05012bfa7ba20d50b0d16813971e46b8a6

@RyanCavanaugh does any of this help?
@evenfrost seeing as we're getting different results could you share your working tsconfig file?

@jasonwilliams here's mine:

{
  "extends": "./tsconfig.base.json",
  "compilerOptions": {
    "allowJs": true,
    "baseUrl": ".",
    "paths": {
      "@/*": [
        "./*"
      ]
    },
    "module": "commonjs",
    "outDir": "./build",
    "rootDir": "./",
    "target": "es2019"
  },
  "exclude": [
    "./build/**/*",
    "./client/**/*",
    "node_modules",
    "**/node_modules/*"
  ]
}

Content of tsconfig.base.json:

{
  "compilerOptions": {
    "allowUnreachableCode": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "noImplicitAny": true,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noUnusedLocals": false,
    "removeComments": true,
    "sourceMap": true,
    "strictNullChecks": true,
    "suppressImplicitAnyIndexErrors": true
  }
}

Thanks I鈥檒l compare against mine

@evenfrost did you try setting useTypescriptIncrementalApi: false in your typescript checker settings?

The stack trace might be enough to go on. We'll give it a shot.

@RyanCavanaugh @rbuckton i've managed to create a test case here:
https://github.com/jasonwilliams/typescript-35801-testcase

Hi there, I also created minimal set for the reproduction.

  1. create index.js with

    let A;
    A = {};
    A.prototype.b = {}
    

    in empty directory.

  2. Run tsc --allowJs --declaration index.js

It throws like:

/usr/lib/node_modules/typescript/lib/tsc.js:81040
                throw e;
                ^

TypeError: Cannot read property 'valueDeclaration' of undefined
    at getBaseConstructorTypeOfClass (/usr/lib/node_modules/typescript/lib/tsc.js:34146:40)
    at serializeAsClass (/usr/lib/node_modules/typescript/lib/tsc.js:32403:42)
    at serializeSymbolWorker (/usr/lib/node_modules/typescript/lib/tsc.js:32202:29)
    at serializeSymbol (/usr/lib/node_modules/typescript/lib/tsc.js:32159:38)
    at /usr/lib/node_modules/typescript/lib/tsc.js:32140:25
    at Map.forEach (<anonymous>)
    at visitSymbolTable (/usr/lib/node_modules/typescript/lib/tsc.js:32139:33)
    at symbolTableToDeclarationStatements (/usr/lib/node_modules/typescript/lib/tsc.js:32031:17)
    at /usr/lib/node_modules/typescript/lib/tsc.js:30890:106
    at withContext (/usr/lib/node_modules/typescript/lib/tsc.js:30910:37)

My tsc is v3.8.3.

I hope this helps you.

This may be related to #36273.

@weswigham I have a fix for the crash, but I'm not sure I like the JS declaration emit for @acomagu's example:

// js
let A;
A = {};
A.prototype.b = {};

// .d.ts
declare class A {
    b: {};
}

The binder declares A as both a FunctionScopedVariable (because of the let) and a Class because of the prototype assignment heuristic. The binder can't know whether its actually a class, so should we be doing some additional work in serializeSymbolWorker to exclude non-class-like symbols (i.e., check that it has both SymbolFlags.Class and some kind of call or construct signature)?

I'm thinking about something like this:

function isEffectiveClassSymbol(symbol: Symbol) {
    if (!(symbol.flags & SymbolFlags.Class)) {
        return false;
    }
    if (isInJSFile(symbol.valueDeclaration) && !isClassLike(symbol.valueDeclaration)) {
        // For a symbol that isn't syntactically a `class` in a JS file we have heuristics
        // that detect prototype assignments that indicate the symbol is *probably* a class.
        // Filter out any prototype assignments for non-class symbols, i.e.
        // 
        //     let A;
        //     A = {};
        //     A.prototype.b = {};
        const type = getTypeOfSymbol(symbol);
        return some(getSignaturesOfType(type, SignatureKind.Construct))
            || some(getSignaturesOfType(type, SignatureKind.Call));
    }
    return true;
}

Hmm, seems reasonable.

One note: not sure if this was stated, but I only ran into this issue with using tsc -b. The tsc -p option didn't have this issue. So (for me) it's only an issue when using the build mode.

Also seeing something similar when converting a vanilla js (does use jsdoc) project over to ts 3.9.4.

tsc works, but tsc -w does not.

downgrading to 3.6.4 and tsc -w does work.

This was fixed in #38508.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Roam-Cooper picture Roam-Cooper  路  3Comments

dlaberge picture dlaberge  路  3Comments

weswigham picture weswigham  路  3Comments

MartynasZilinskas picture MartynasZilinskas  路  3Comments

seanzer picture seanzer  路  3Comments