Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
jasonwilliams opened this issue Dec 20, 2019 · 19 comments
Assignees
Labels
Bug A bug in TypeScript Rescheduled This issue was previously scheduled to an earlier milestone

Comments

@jasonwilliams
Copy link

This is a continuation of #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:
#34869

@jasonwilliams
Copy link
Author

@evenfrost @arian @BernsteinA @elibarzilay new issue here

@RyanCavanaugh
Copy link
Member

@jasonwilliams how do we reproduce the issue?

@jasonwilliams
Copy link
Author

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

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

@evenfrost
Copy link

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).

@evenfrost
Copy link

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.

@jasonwilliams
Copy link
Author

jasonwilliams commented Jan 2, 2020

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

@jasonwilliams
Copy link
Author

jasonwilliams commented Jan 2, 2020

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
29becf0

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

@evenfrost
Copy link

@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
  }
}

@jasonwilliams
Copy link
Author

jasonwilliams commented Jan 5, 2020

Thanks I’ll compare against mine

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

@RyanCavanaugh RyanCavanaugh added the Bug A bug in TypeScript label Jan 13, 2020
@RyanCavanaugh RyanCavanaugh added this to the TypeScript 3.9.0 milestone Jan 13, 2020
@RyanCavanaugh
Copy link
Member

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

@jasonwilliams
Copy link
Author

@acomagu
Copy link

acomagu commented May 6, 2020

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.

@rbuckton
Copy link
Member

rbuckton commented May 8, 2020

This may be related to #36273.

@rbuckton
Copy link
Member

rbuckton commented May 9, 2020

@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)?

@rbuckton
Copy link
Member

rbuckton commented May 9, 2020

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;
}

@weswigham
Copy link
Member

Hmm, seems reasonable.

@RyanCavanaugh RyanCavanaugh added the Rescheduled This issue was previously scheduled to an earlier milestone label May 20, 2020
@matthew-dean
Copy link

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.

@bartcone
Copy link

bartcone commented Jul 8, 2020

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.

@andrewbranch
Copy link
Member

This was fixed in #38508.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Rescheduled This issue was previously scheduled to an earlier milestone
Projects
None yet
Development

No branches or pull requests

10 participants