typescripttypescript-compiler-api

TypeScript compiler API get value / type of import


Consider the following code:

// file1
export const VIEWPORT_HEIGHT = 1080;

// file2
import { VIEWPORT_HEIGHT } from '../../constants/app';

While processing file2, how can I get the value / type of VIEWPORT_HEIGHT? Given that it's a constant, its type will be 1080, not number. I'm trying to accomplish the same as VSCode which shows the constant value when you hover over the import:

enter image description here

While processing the import, I can analyse the following AST:

ImportDeclaration > ImportClause > NamedImports > ImportSpecifier > Identifier

I have access to the program that webpack's ts-loader passes to getCustomTransformers and thus I have access to the type checker by doing:

let checker = program.getTypeChecker();

But I'm unable to reach the value / type. What am I missing?


Solution

  • I've figured this out.

    I can pass any declaration to the type checker to obtain its value. Here's an example:

    const ts = require('typescript');
    
    function createConstInlinerTransformer(program) {
      const factory = ts.factory;
      const checker = program.getTypeChecker();
    
      function transformerFactory(context) {
        return {
          transformSourceFile(sourceFile) {
            const visitor = function (node) {
              // The sourceFile node contains the following:
              // sourceFile.symbol.exports
              // sourceFile.locals
              // We can use these to obtain the values of variables and imports.
    
              // import
              const firstImportClause = sourceFile.statements[0].importClause;
              checker.getTypeAtLocation(firstImportClause.namedBindings.elements[0].symbol.declarations[0])
    
              // local const
              const localVar = sourceFile.locals.get('someVar');
              checker.getTypeAtLocation(localVar.valueDeclaration);
    
              // exported const
              const exportedVar = sourceFile.symbol.exports.get('someExportedVar');
              checker.getTypeAtLocation(exportedVar.valueDeclaration)
    
              return ts.visitEachChild(node, visitor, context);
            };
    
            return ts.visitNode(sourceFile, visitor);
          },
        };
      }
      return transformerFactory;
    }
    
    module.exports = { createConstInlinerTransformer };