[ts-transform-paths] Error when using with transpileModule.
IgorSzymanski opened this issue · 2 comments
When running an application using in ts-node
with --transpile-only
flag (or ts-node-dev
) and ttypescript
with ts-transform-paths
plugin, the plugin doesn't seem to work.
I did some research and the reason is transpile-only
of ts-node
mode and ts-node-dev
compile the code using transpileModule
function of the main typescript
library.
Now, ts-transform-paths
gets info about paths from an object implementing the interface Program
transformationContext.getCompilerOptions()
Here is the interface:
https://github.com/microsoft/TypeScript/blob/167f954ec7cf456238cad4f2006fb330c53bba8e/src/compiler/types.ts#L3195-L3300
The transformationContext
is created by TS itself, but when it's created inside transpileModule
function, things get a bit weird...
(Here's the line where the Program
instance is created).
https://github.com/microsoft/TypeScript/blob/167f954ec7cf456238cad4f2006fb330c53bba8e/src/services/transpile.ts#L90
const program = createProgram([inputFileName], options, compilerHost);
Because the options that are passed to the factory are not exactly what's in tsconfig.json
.
And here are the lines that are responsible for that:
https://github.com/microsoft/TypeScript/blob/167f954ec7cf456238cad4f2006fb330c53bba8e/src/services/transpile.ts#L32-L41
const defaultOptions = getDefaultCompilerOptions();
for (const key in defaultOptions) {
if (hasProperty(defaultOptions, key) && options[key] === undefined) {
options[key] = defaultOptions[key];
}
}
for (const option of transpileOptionValueCompilerOptions) {
options[option.name] = option.transpileOptionValue;
}
What this fragment does is it takes this array:
https://github.com/microsoft/TypeScript/blob/167f954ec7cf456238cad4f2006fb330c53bba8e/src/compiler/commandLineParser.ts#L224-L1000
And replaces each property of tsconfig.json
with the value of matching transpileOptionValue
property, and in case of paths
it's:
{
// this option can only be specified in tsconfig.json
// use type = object to copy the value as-is
name: "paths",
type: "object",
affectsModuleResolution: true,
isTSConfigOnly: true,
category: Diagnostics.Module_Resolution_Options,
description: Diagnostics.A_series_of_entries_which_re_map_imports_to_lookup_locations_relative_to_the_baseUrl,
transpileOptionValue: undefined
},
undefined
So when ts-transform-paths
tries to resolve paths in a transpileOnly
mode, it cannot do so, because the config it gets in this mode using this
transformationContext.getCompilerOptions();
has paths
set to undefined
.
The summary is: getCompilerOptions()
of a Program
instance is not a reliable way of accessing info about paths
, because the data is lost in transpileOnly
mode. There should be another way to access such data, because they probably won't change the behaviour in typescript
library, because they always consider such things intentional.
You can see the library failing in this repo:
https://github.com/IgorSzymanski/ts-transform-paths-bug-repro
Either run
yarn
yarn start:dev
or
yarn
yarn start:transpile
on the contrary:
yarn
yarn start:live
Will work just fine, because it's not using transpileOnly
mode.
Would be great to get this working! I mentioned it in this issue on ts-node and there is some more context there as well.
FYI - typescript-transform-paths now supports being used without a Program
instance. It's now usable via ts-node --transpileOnly
. I am currently in process of simplifying it to work via it's own register script