Hey guys, thank you for your hard work and everything!
I hope it's OK to ask questions about TypeScript API here, due to the lacking documentation and it's complexity.
I'm working on a custom build tool and I'm trying to call TypeScript compiler directly to compile source code. However, the examples in documentation doesn't explain much regarding the loading/parsing the configuration files, so I've tried to figure out it myself, using examples from other similar projects.
My question is regarding the createProgram() function. I'm trying to mimic the tsc behavior. In tsconfig.json documentation there are only files, include and exclude options and there is nothing about a root names. What exactly should I put into this argument?
I have many files in my project and not everything is available through the root index.ts module. I have individual modules like src/*.spec.ts for tests as well. However, if I put index.ts into rootNames, then only modules resolved from index.ts is emitted, but all other individual files are just omitted from the compilation for some reason.
Could you explain a bit, how should I call the compiler in order to process all files mentioned in include array and not only the root files and their dependencies?
Here's the code I use right now for compilation:
const extraCompilerOptions: CompilerOptions = {
typeRoots: [
`${options.projectDir}/node_modules/@types`,
`${options.projectDir}/types`
],
outDir: options.outputDir,
declarationDir: options.declarationsOutputDir
};
const readConfig = typescript.readConfigFile(options.tsConfigPath, typescript.sys.readFile);
// I'm adding include/exclude properties externally
Object.assign(readConfig.config, {
include: options.include,
exclude: options.exclude,
});
const parsedConfig = typescript.parseJsonConfigFileContent(
readConfig.config,
typescript.sys,
dirname(options.tsConfigPath),
extraCompilerOptions
);
const program = typescript.createProgram(['index.ts'], parsedConfig.options);
const emitResult = program.emit();
Maybe I'm missing some important bits? Any suggestions will be highly appreciated, thanks!
When calling tsc inside the project directory, performCompilation is called with configParseResult.fileNames.
configParseResult is built with parseConfigFileWithSystem > getParsedCommandLineOfConfigFile > parseJsonConfigFileContentWorker > getFileNames.
Try building tsc yourself and putting a breakpoint in getFileNames to see how it is traversing the directory.
Thanks @agentcooper for internals explanation. However, could you also explain from the conceptual point of view, what should go to the rootNames (from the compiler API standpoint) and why I'm experiencing the result where only root modules are compiled. Do I need to resolve all modules manually and pass them as rootNames or something?
configParseResult.fileNames ends up getting passed as rootNames
@RyanCavanaugh I see, but was is relation between include/exclude/files and rootNames? How does it all works together?
include, exclude, and files are all tsconfig-only things that work together to produce a set of rootNames.
Yes, that was my though. However, what confused me is that include and exclude is affecting the compilation process as well, so it must be not only used to construct rootNames?
Most helpful comment
When calling
tscinside the project directory,performCompilationis called withconfigParseResult.fileNames.configParseResultis built withparseConfigFileWithSystem>getParsedCommandLineOfConfigFile>parseJsonConfigFileContentWorker>getFileNames.Try building
tscyourself and putting a breakpoint ingetFileNamesto see how it is traversing the directory.