Typescript Compiler API:How to get absolute path to source file of import module using typescript compiler api

1.9k views Asked by At

I try to get the path information as follows:

  const typeChecker = program.getTypeChecker();
  const importFileSymbol = typeChecker.getSymbolAtLocation(
    importDeclarationNode.moduleSpecifier
  );
  const path = importFileSymbol?.valueDeclaration?.path || '';

In this way, I can get the sourceFile object of the module source file, and get the absolute path of the module through the path attribute on sourceFile. But path is an internal property of typescript and does not expose the type, so I think there may be some problems with this usage.

So I wonder if there is any other way to get it?

I also tried to get it through the fileName property of sourceFile, but for modules imported through path mapping, the obtained path is not an absolute path。

1

There are 1 answers

3
denalisk On BEST ANSWER

I haven't done it exactly as you're trying to parse it, but I was able to use the resolveModuleName method in the typescript API to accomplish what you're asking, following the docs here

import * as fs from 'fs';
import * as ts from 'typescript';

function resolvePathsToModuleImports(typescriptFilePath: string) {
    // To use the typescript module resolution, you need to get the tsconfig
    // Here we assume you already have a reference to the tsconfig JSON
    const tsConfigObject = ts.parseJsonConfigFileContent(
        TSCONFIG_JSON_CONTENT,
        ts.sys,
        PATH_TO_BASE_OF_PROJECT
      );

    const fileContent = fs.readFileSync(typescriptFilePath).toString();
    // Preprocess the typescript file using the compiler API
    // to get the raw imports as represented in the file
    const fileInfo = ts.preProcessFile(fileContent);

    // You can then get the file path, etc, by resolving the imports via the
    // compiler API
    fileInfo.importedFiles
        .map(importedModule => importedModule.fileName)
        .forEach(rawImport => {
            const resolvedImport = 
                ts.resolveModuleName(
                    rawImport, 
                    typescriptFilePath, 
                    tsConfigObject.options, 
                    ts.sys);
            // Depending on how fancy your ts is, the
            // "resolvedImport.resolvedModule.resolvedFileName" may not exist,
            // but should resolve for all ts files
            const importLoc = resolvedImport.resolvedModule.resolvedFileName;
            console.log(`File ${typescriptFilePath} imports ${rawImport} from location ${importLoc}`);
        });
}