Typescript: TypeError: Cannot read property 'kind' of undefined at getErrorSpanForNode

Created on 13 Sep 2020  路  5Comments  路  Source: microsoft/TypeScript

There's a PR open for this one.

Under some set of rituals and incantations I have not been able to replicate, tsc throws the following error:

image

There's been several bugs open - and fixed - around this.

I could not replicate, it was easier to fix. The fix addresses a simple logical inconsistency where a safety check happened after it was necessary.

Crash Needs More Info

Most helpful comment

After some more testing typescript@next seems to handle the above case correctly,

$ ./node_modules/.bin/tsc --version
Version 4.1.0-dev.20201015
$ ./node_modules/.bin/tsc
test.js:1:1 - error TS8006: 'import type' declarations can only be used in TypeScript files.

1 import type { x } from 'y'
  ~~~~~~~~~~~~~~~~~~~~~~~~~~

Found 1 error.

All 5 comments

I opened a PR - https://github.com/microsoft/TypeScript/pull/40523 - that fixes this in a sort of hacky way. I wasn't able to figure out what set of rituals, incantations, and sacrifices I needed to make in order to replicate this with even a subset of our source repository. I believe it has to do with existing Flow annotations, but that's a hunch. Either way, there's a deeper issue where the signature of getErrorOrSpanForNode does not ever expect a node to be undefined, but clearly an undefined node sometimes sneaks through. The fix might be considered more of a workaround because I'm just testing for the node itself to be undefined, but with the signature not expecting it, my gut instinct is to think there's a deeper issue where a value is undefined unexpectedly elsewhere. I am not, however, familiar enough with tsc internals to say more than that unfortunately.

This particular issue is blocking my evangelism at work, so can the workaround be accepted?

Quoting my response from the PR:

As a start, from what I can see, this is happening from syntax checks in a JavaScript file (i.e. .js or .jsx) to ensure that TypeScript-specific syntax isn't being used somewhere. This is indicated by the call getJSSyntacticDiagnosticsForFile.

Like I mentioned in the review, something is going wrong because some caller is lying about its types. There is exactly one call to createDiagnosticForNode that has a type assertion on the node passed in:

                        case SyntaxKind.AsExpression:
                            diagnostics.push(createDiagnosticForNode((node as AsExpression).type, Diagnostics.Type_assertion_expressions_can_only_be_used_in_TypeScript_files));
                            return "skip";

https://github.com/microsoft/TypeScript/blob/57c8938d9e90dd4ece5389d4c78593db1ea22e81/src/compiler/program.ts#L1911-L1912

If you can at least narrow down a section in a .js file that causes this to happen, then that'd help.

You can also add a line in tsc.js to just tell you which file you're hitting. The change in the original source code would be:

                         case SyntaxKind.AsExpression:
+                            Debug.assertIsDefined((node as AsExpression).type, "Expected asserted type node to be present in " + sourceFile.fileName);
                             diagnostics.push(createDiagnosticForNode((node as AsExpression).type, Diagnostics.Type_assertion_expressions_can_only_be_used_in_TypeScript_files));

or pinpoint the expression that's causing issues:

```diff
- diagnostics.push(createDiagnosticForNode((node as AsExpression).type, Diagnostics.Type_assertion_expressions_can_only_be_used_in_TypeScript_files));
+ diagnostics.push(createDiagnosticForNode(node, Diagnostics.Type_assertion_expressions_can_only_be_used_in_TypeScript_files));

I believe I'm having the same issue as you having to do with legacy flow types tripping up the compiler. Typescript seems to be tripping up on import type statements if they appear in js files. Not sure if the pr already fixed this but here's a more contained test case if the Needs more Info tag still applies.

$ ./node_modules/.bin/tsc --version
Version 4.0.3

$ ./node_modules/.bin/tsc
/Users/eric/tmp/tserror/node_modules/typescript/lib/tsc.js:84774
                throw e;
                ^

TypeError: Cannot read property 'kind' of undefined
    at getErrorSpanForNode (/Users/eric/tmp/tserror/node_modules/typescript/lib/tsc.js:10173:22)
    at Object.createDiagnosticForNodeInSourceFile (/Users/eric/tmp/tserror/node_modules/typescript/lib/tsc.js:10124:20)
    at createDiagnosticForNode (/Users/eric/tmp/tserror/node_modules/typescript/lib/tsc.js:85010:31)
    at walk (/Users/eric/tmp/tserror/node_modules/typescript/lib/tsc.js:84876:50)
    at visitAllPossibleChildren (/Users/eric/tmp/tserror/node_modules/typescript/lib/tsc.js:22063:31)
    at Object.forEachChildRecursively (/Users/eric/tmp/tserror/node_modules/typescript/lib/tsc.js:22024:23)
    at /Users/eric/tmp/tserror/node_modules/typescript/lib/tsc.js:84849:20
    at runWithCancellationToken (/Users/eric/tmp/tserror/node_modules/typescript/lib/tsc.js:84767:24)
    at getJSSyntacticDiagnosticsForFile (/Users/eric/tmp/tserror/node_modules/typescript/lib/tsc.js:84846:20)
    at getSyntacticDiagnosticsForFile (/Users/eric/tmp/tserror/node_modules/typescript/lib/tsc.js:84759:65)

tsconfig.json

{
    "compilerOptions": {
        "noEmit": true,
        "allowJs": true
    },

    "include": ["test.js"]
}

test.js

import type { x } from 'y'

After some more testing typescript@next seems to handle the above case correctly,

$ ./node_modules/.bin/tsc --version
Version 4.1.0-dev.20201015
$ ./node_modules/.bin/tsc
test.js:1:1 - error TS8006: 'import type' declarations can only be used in TypeScript files.

1 import type { x } from 'y'
  ~~~~~~~~~~~~~~~~~~~~~~~~~~

Found 1 error.
Was this page helpful?
0 / 5 - 0 ratings