Skip to content

TypeChecker.getTypeAtLocation throws runtime errors when passed valid nodesΒ #48878

Closed

Description

@Zamiell

Bug Report

Similar to #47041.

πŸ”Ž Search Terms

  • TypeChecker
  • getTypeAtLocation
  • flags
  • undefined

πŸ•— Version & Regression Information

No idea, probably not applicable.

⏯ Playground Link

I can't link to the playground because this issue is about an internal class that is exposed.

Problem

The problem is that I get a run-time error when using the TypeChecker.getTypeAtLocation method in certain contexts.

This is because the signature for the method is wrong. It allows you to pass in a ts.VariableDeclaration, which is a bug, because in some cases doing that will throw a run-time error. For the exact error, see the subsequent section.

πŸ’» Code

Consider the following TypeScript code:

const myArray = [1];
const [firstElement] = myArray;

When we iterate over the AST for this code, and we get the types of every variable declaration, we get a runtime error when calling the getTypeAtLocation function:

  // Create an ESLint plugin
  create(context) {
    const parserServices = util.getParserServices(context);
    const typeChecker = parserServices.program.getTypeChecker();
    const sourceFiles = parserServices.program.getSourceFiles();
    for (const sourceFile of sourceFiles) {
      // We skip over all files except for the one containing the Jest test
      // that triggers the buggy runtime error
      if (!sourceFile.getText().includes("myArray")) {
        continue;
      }

      for (const statement of sourceFile.statements) {
        const variableStatement = statement as ts.VariableStatement;
        for (const declaration of variableStatement.declarationList.declarations) {
          console.log("Iterating over:", declaration.getText());
          const tsType = typeChecker.getTypeAtLocation(declaration); // CRASH HERE
        }
      }
    }

    return {};
  },

The exact runtime error is as follows:

TypeError: Cannot read properties of undefined (reading 'flags')
      at Object.getCheckFlags (../../node_modules/typescript/lib/typescript.js:19286:23)
      at getTypeOfSymbol (../../node_modules/typescript/lib/typescript.js:55760:33)
      at getTypeOfNode (../../node_modules/typescript/lib/typescript.js:84915:24)
      at Object.getTypeAtLocation (../../node_modules/typescript/lib/typescript.js:47415:31)
      at create (src/rules/strict-enums.ts:65:38)
      at create (../utils/dist/eslint-utils/RuleCreator.js:48:20)
      at Object.create (../../node_modules/eslint/lib/rule-tester/rule-tester.js:533:73)
      at createRuleListeners (../../node_modules/eslint/lib/linter/linter.js:887:21)
      at ../../node_modules/eslint/lib/linter/linter.js:1069:31
          at Array.forEach (<anonymous>)

Solution

This code can be fixed by changing the following line:

const tsType = typeChecker.getTypeAtLocation(declaration); // "declaration" is of type "ts.Declaration"

To:

const tsType = typeChecker.getTypeAtLocation(declaration.name); // "name" is of type "ts.BindingName"

In other words, the problem is that you are "supposed" to pass it a variable of type "ts.BindingName" instead of type "ts.Declaration".
But this is not represented in the function type signature. (Normally, when you pass a wrong variable into a function, the TypeScript compiler tells you about it.)

When I asked Nathan Sanders if it was feasible to change the signature, he said:

maybe not impossible for this particular one, but definitely difficult, and maaaybe impossible

Thus, I think that there should be a run-time check added to the source code for the getTypeAtLocation function that checks to see if symbol is undefined, and if it is, returns an "empty" type, or something along those lines.

Adding this check would likely fix #47041 automatically.

Activity

  1. added
    Effort: CasualGood issue if you're already used to contributing to the codebase. Harder than "good first issue".
    on Apr 29, 2022
  2. locked as resolved and limited conversation to collaborators on Oct 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScriptEffort: CasualGood issue if you're already used to contributing to the codebase. Harder than "good first issue".

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions