Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeError: _extends.endsWith is not a function in utils.js when using extends property as an array in TypeScript 5+ #14

Closed
chrisfentiman opened this issue May 7, 2023 · 4 comments · Fixed by #15

Comments

@chrisfentiman
Copy link

chrisfentiman commented May 7, 2023

When using TypeScript 5+ and configuring the tsconfig property "extends" as an array in the tsconfig.json file, the following error is thrown in the utils.js file:

/node_modules/tsconfig-to-swcconfig/dist/utils.js:35
if (!_extends.endsWith('.json')) {
              ^

TypeError: _extends.endsWith is not a function

This error occurs because the code expects "extends" to be a string. In TypeScript 5+, the extends property in the tsconfig.json file can now be a string or an array.

You can see the update here: microsoft/TypeScript#29118

Steps to reproduce:

  1. Use TypeScript 5+
  2. Set the extends property in the tsconfig.json file as an array.
  3. Run the project.

Expected behavior:

The project should run without any errors.

Actual behavior:

The error mentioned above is thrown in the utils.js file.

Possible solution:

This solution is dependent on the desired direction for the package:

1. Manual approach

To address the issue, you can manually check if the extends property is an array or string in the tsconfig.json file. If it is a string, maintain the current behavior. If it is an array, you can do the following:

  1. Iterate through each element in the extends array and attempt to load the corresponding tsconfig.json file.
  2. Merge the tsconfigs deeply, ensuring that the order of the tsconfigs is respected. This means that the first tsconfig is overwritten by subsequent tsconfigs, and the last tsconfig is the one the user provided.
  3. This should resolve the error and produce the expected output.

2. Use typescript

The previous solution may not be future-proof, as it tries to mimic the expected behavior of typescript rather than relying on TypeScript to compile the tsconfig and using the output to generate the swcconfig.

You can rely on TypeScript's inner workings to generate the complete tsconfig without worrying about compiling it, as follows:

import * as ts from 'typescript';

const configFileName = 'tsconfig.json';
const { config, error } = ts.readConfigFile(configFileName, ts.sys.readFile);
if (error) {
    console.error(error);
    process.exit(1);
}

const parsedConfig = ts.parseJsonConfigFileContent(config, ts.sys, './');
const compilerOptions = ts.convertCompilerOptionsFromJson(parsedConfig.options, './', configFileName);

console.log(compilerOptions.options);

This code generates the complete tsconfig as expected, without compiling it manually. You can leverage the inner workings of TypeScript to resolve the tsconfig and then use it to map the swcconfig.

Affected Package:
tsconfig-to-swcconfig

Version:
2.2.0

Platform:

  • Node 18.14
  • Typescript 5.0.4
@songkeys
Copy link
Owner

songkeys commented May 8, 2023

Thank you for the report! For the second solution, I didn't use Typescript as a dependency because it was too large for the file loading requirements. However, now I believe it is more promising as you pointed out; we can make it a peer dependency since every project with a tsconfig.json file should already have Typescript installed. What do you think?

@chrisfentiman
Copy link
Author

While I agree that TypeScript is a large dependency, I believe it is reasonable to assume that anyone using tsconfig-to-swcconfig is a TypeScript user and would already have the TypeScript dependency installed. Therefore, making TypeScript a peer dependency of the package seems like a logical approach, which will also reduce the package size and improve installation times.

However, with this new dependency, the package will also need to clearly state what versions of TS it supports and be able to handle changes in the API for backward compatibility. Quickly crunching some numbers from NPM downloads over the last 7 days, it's pretty safe to assume that if the package supports TS v3+, it will cover the majority of users.

This would be a large package refactor and a robust test suite to ensure backward compatibility. However, I think the effort is worth the reward, as I have not found a package that does tsconfig to swc well, and seeing as swc has no desire to do this, feels worth it.

@songkeys
Copy link
Owner

songkeys commented May 10, 2023

Could you please take a look at PR #15? I also released tsconfig-to-swcconfig@2.2.0-alpha.0, which you can try out on your machine. Let me know if it works for you.

I just checked out the typescript implementation. There is a ts.readConfigFile function, but it only reads; we still need to manually merge extends. (Please let me know if I'm mistaken about this). So I decided to stick with the current implementation.

@chrisfentiman
Copy link
Author

Hi @songkeys,

This looks great - on inspection, it seems to operate the way you intend. Unfortunately, this approach/package didn't work for our company and so we decided to go in a different direction to create a package that wasn't dependent on anything except the users' environment. We've also added a number of other features to the conversion process.

However - I do believe that your fix will resolve the original issue.

If you wanted to checkout how we solved the issue see -> https://github.com/ConvertibleCo/tswig

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants