aurelia / i18n

A plugin that provides i18n support.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

TypeScript compile error in typings for v3.1.2

josundt opened this issue Β· comments

I'm submitting a bug report

  • Library Version:
    3.1.2

  • Operating System:
    Windows [10]

  • Node Version:
    LTS

  • NPM Version:
    LTS

  • Language:
    TypeScript 4.0.2

In aurelia-i18n@3.1.2, the typings (aurelia-i18n/aurelia-i18n.d.ts) causes a TypeScript compile error.

The error is related to the import statement for i18next on line 6 in aurelia-i18n/aurelia-i18n.d.ts:

import { i18next } from 'i18next';

This line was correct in the previous release (3.1.1) but has for some reason changed. It should still have been like before:

import i18next from 'i18next';

PS! I have i18next@14.1.1 installed which comes with included typings, so I have don't have the @types/i18next package installed as it should not be required.

When looking at the i18next typings, you see that i18next is a default export:

declare namespace i18next {
    //[...]
}

declare const i18next: i18next.i18n;
export default i18next;

Not sure why this line changed since the 3.1.1 release, but it is a showstopper from upgrading in typescript projects.
Hopefully this is an easy fix that can be fixed quickly followed by an update released as soon as possible.

Not really because it would force users to have additional settings in their tsconfig. Besides that while default exports are common in React and other frameworks they're not really seen as a good practice. We had this one popping up several times in existing issues.

We'll certainly have to look again closely what to do with it going forward

@zewa666 The current typings break the TypeScript compilation regardless of the tsconfig settings you use

I believe that the tsconfig settings you referred to are allowSyntheticDefaultImports and/or esModuleInterop - which allows using "default import syntax" (similar to BabelJS) for interoperability with CommonJS modules. Personally I prefer not changing the defaults for these tsconfig settings (false), I rather prefer the import * as name from "module" syntax when I can.

But the value of these tsconfig settings should not matter for i18next import, because i18next is exported as an actual default export - both in the ES module compilation and the CommonJS compilation - and should therefore be imported using default import syntax. (i18next >= 14.1.1). Whether default exports/imports is a good practice may not matter much - I guess when i18next has exported it as a default export - the consumers don't have many other choices than importing it using a default import statement πŸ™‚

From i18next/dist/es/index.js (referenced in package.json "module" - the one used when bundling with webpack), line 3:

export default i18next;

From i18next/dist/commonjs/index.js (referenced in package.json "main"), line 14:

exports.default = _i18next2.default;

When the i18next library is using actual default exports, the import statement in the typings should also use default import syntax

import i18next from i18next;

...and no special tsconfig settings should be required.

The current import statement in your typings

import { i18next } from i18next;

will cause TypeScript compilation errors with any tsconfig settings.

I have now tested this in my project:

  • I have modified the import statement in node_modules/aurelia-i18n/dist/aurelia-i18n.d.ts to import 18next from i18next;
  • Then in my tsconfig.json, I have tested all possible combinations of allowSyntheticDefaultImports and esModuleInterop.
  • ...compilation was successful with any of these tsconfig settings! (TypeScript 4.0.2).

But without this change in the typings file, compilation fails with any combination of the mentioned tsconfig settings.

Please fix this because the current typings will break compilation in any typescript project regardless of what the tsconfig settings are.

PS! I found something that may be clarifying. There seems to be a difference in the typings in the @types/i18next package used in your repository (v8.4.5) and the ones that come with the i18next (v14.1.1) package:

From the @types/i18next@8.4.5 typings:

declare namespace i18next {
    // [...]
}

declare const i18next: i18next.i18n;
export = i18next;

From i18next@14.1.1 typings:

declare namespace i18next {
    // [...]
}

declare const i18next: i18next.i18n;
export default i18next;

The @types/i18next package has been deprecated, you should now use the one included in i18next instead. These typings also express correctly how i18next is actually exported (in the latest version) - as a default export.

With the @types/i18next package I can see how tsconfig settings may have played a role - with the latest typings in i18next it should not matter!

Thx for looking into it. I will take a look asap and I'm sure we'll be rolling a fix out soon. Meanwhile if this is a blocker for you I'd recommend patch-package which allows you to safely navigate around the issue by patchfixing the d.ts file after npm installs.

Np. Sorry for causing all this work lately :-)
And sorry for adding as much text as I have in this case.
The compressed information is:

  • the deprecated @types/i18next typings may have been vulnerable to different tsconfig settings - but the included typings with latest i18next should not have this problem.
  • until the import is changed to `import i18next from 'i18next' in your typings, there will be compile errors for TypeScript projects - at least when @types/i18next is not installed
  • What should be done: remove @types/i18next from the repo devDependencies, potentially update i18next to lastest (14.1.1) and inform users to uninstall @types/i18next.

Please let me know if you my contribution for this fix.
I realized I was involved in this earlier as well (#237).

Aahh I wasn't sure but had the idea that the two of us already had contact with that issue. Thanks again and no absolutely no disturbance, it's me who's in debt with the low time.

If you can create a PR with your change it would be super helpful for testing. I should be able to take a look at it over the weekend.

Good news is that me new job is finally again going to involve this plugin so it should certainly get much better time wise after the initial ramp up

Added a PR now that should fix the problem (#325).
It would be nice to have this released ASAP since the 3.1.2 release will be problematic for Aurelia TypeScript based projects.

A small unrelated tip I wanted to mention that could save you some time - since it seems we are both working on Intl/Jest/full-icu testing. I found that running tests using the command cross-env NODE_ICU_DATA=node_modules/full-icu jest failed for me when running multiple tests in parallel (Windows) - icu was not loaded in all child processes. I therefore had to add a Jest globalsetup file instead and set process.env.NODE_ICU_DATA="node_modules/full-icu" there...

thanks again for the quick help, I was literally turning up VSCode to start looking at the issue. What a service ;)
I realized over at the Aurelia v2 version of the plugin we're already on 17.x thats why we didn't have the issue there. So thanks for the great catch.

By time, and once v2 alpha bubbles up I'll take the time to update the v1 plugins dependency as well and ship it with the next major. But for now we should be definitely good. Thanks again and after pinging @EisenbergEffect 3.1.3 should be on it's way soon.

@zewa666 Just testet out the 3.1.3 release. Looks like the typings file (aurelia-i18n.d.ts) file has not been updated.
PSI In my PR, I did not include changes in the "dist" folder as I have earlier been instructed not to do that. I assume some CI job normally takes care of building the content of this folder.
In aurelia-i18n@3.1.3, it looks like npm run build has not been run before releasing the package so the dist folder seems identical to previous release πŸ™
Looks like we need even one more release to solve this then...

there was something totally strange since the change you did for 3.1.3 already landed previously and got released with 3.1.2 if you look at the repos commit history. I'm unsure how this happened but frankly when I just created a fresh new Webpack TS project and added aurelia-i18n I have no issues and all works. The i18next dependency is ^14.1.1 and no types/i18next present. So it seems ok to me, do you experience any issues?

ok now I think I see the issue. If I try to inject I18N and then instance.i18next.use I get a type info. Now the built in typings export still via export default i18next; which is why we still need our script we had before that changes from named to default import.

God, the typings of i18next are really so messed up and these default exports are really giving me a grind. Can you verify that @josundt ?

I now realize that I have made a mistake.
The fixI18nDefaultImport function was actually fixing the problem, not causing it 😫
The function was replacing import { i18next } from 'i18next' with import i18next from 'i18next' (desired), so it was a mistake from my side to remove it from the build script in my last PR

But when aurelia-i18n@3.1.2 was built, for some reason the fixI18nDefaultImport function can not possibly have been called, because in this package release, the i18next import statement in the typings file was not fixed expectedly.
When I tested updating the package to 3.1.2 in my Aurelia project and discovered the typings issue, I had a look at the build script - and I assumed that the function was called like it should during the package build.

I regretfully did not read the function code carefully, so I assumed that fixI18nDefaultImport was doing the exact opposite of what it did; I thought it was replacing import i18next from 'i18next' with import { i18next } from 'i18next', not the other way around! I obviously should have read the function code more thoroughly, but since I assumed that the function had run and that the typings file I saw was a result of that, I understand why I jumped to this wrong conclusion.

The bottom line of this issue: The problem with the 3.1.2 release was that the fixI18nDefaultImport function for some reason never fixed the typings like expected. The question is why. This has not been a problem in preceding releases.
AND: The function should NOT have been removed by me - I unfortunately did this in my previous PR preceding the the 3.1.3 release. (So in the 3.1.3 release the typings were bound to get wrong. Really sorry about that...)

@zewa666 I think I have shared all my insights about this issue, but I don't know how to investigate what went wrong in the 3.1.2 release since typings were not fixed. Do you think you could figure this out from here and hopefully release yet another version - hopefully with the correct typings once and for all?

I am not familiar with all aspects of this package's build process, and I never used the dts-bundle-generator myself. In the packages I have made, I have normally generated typings simply by running tsc using an extra tsconfig file that inherits from the base one, with these additions

{ 
 "declaration": true,
 "declarationDir": "./dist/typings",
 "emitDeclarationOnly": true
}

Then, in 'package.json' I set the 'typings' property to the entry point module typings file, e.g. 'dist/typings/i18n.d.ts'.

It looks like the purpose of the dts-bundle-generator is to bundle all types into one d.ts file, but also to exclude redrundant types - including only the types referenced in dependency graph of the exported types'; like some kind of "tree-shaking for types". I understand the rationale.

But since all i18next import statements in your typescript source code (e.g. './src/i18n.ts', './src/t/t-value-converter') use correct default imports (import i18next from 'i18next'), I find it strange that in the output of the dts-bundle-generator it has been changed to import { i18next } from 'i18next'. This is suspicious and makes me question the reliability of the tool. It may seem as if this tool does not adhere the earlier discussed tsconfig settings in the project (allowSyntheticDefaultImports, esModuleInterop).

I don't see any great benefits of bundling typings into one file. Maybe the "types tree-shaking" feature delivers a tiny performance benefit for the typescript compiler/language service by removing redundant types, but maybe it's not really worth it if it incorrectly alters import statements etc. like I suspect?

Agree the dts-bundle-generator is an old relict from early Aurelia times. It certainly is going to be got rid of but was postponed to be done with the next major update.

So bottom line, the generated aurelia dts file should have import i18next from 'i18next'; as it used to be with the fixup task (like in 3.1.1) so the actual change is merely to have an updated i18next dependency and the drop of the @types package right?

If so I'll create a fix for that and get it deployed.

When on to the update for the latest major I'll make sure these things get addressed in a better way. This is now being too often an issue.

@zewa666 That's exactly right πŸ‘.
But please also make sure that the typings fix is actually is applied to aurelia-i18n.d.ts in the dist folder before publishing the package, since it for some reason did not happen in the 3.1.2 release...

might be to add a typescript test. took me a little to follow the trail after getting the error after an yarn upgrade

@zewa666 Will you be able to fix this and make yet another release?
It should be more or less just to revert to the commit for the 3.1.2 release, but to figure out why the typings fix was not applied by the build preceding the package publishing of 3.1.2.

hey guys, sorry that it took me so long. I've created the PR could you give it another look @josundt just to be safe :)

I guess that should really be it. Aside from the fix I've also made sure to update the jspm dependency which wasn't the same as the npm dependency.

@zewa666 I pulled your PR branch and looked at the code.
After running npm run build the generated typings file is completely correct, but the file in the repo is incorrect before running npm run build .
As mentioned I don't fully understand build/release process; why the dist folder is not in .gitignore and why the dist folder should not be commited in PRs.
But if npm run build is executed before npm publish for the upcoming version; the package should end up completely correct πŸ‘

Released 3.1.4

It's been a bumpy road but it seems we finally we nailed it πŸ˜€
Thanks a lot!

@josundt the dist folder is not in gitignore since it contains the transpiled code for eg npm instalations. it shouldn't be commited (outside releases) since it's superficial and would make reviews 50times harder.