-
-
Notifications
You must be signed in to change notification settings - Fork 43
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
add named export #17
add named export #17
Conversation
@lukeed The linked commit actually does NOT fix this. Now you removed the TS error for the first case, but created one for the second case. |
This was a breaking change, and not something I want -- sorry. It's intentionally a default export, which means that this is/was the correct variant: import klona from 'klona'; You should check your TS config. You probably want In any event, your TS was loading the file incorrectly (adding a import klona = require('klona'); Either way, I've updated the type definitions so that it works regardless of how you decide to import the module. |
@d-fischer Both of these are absolutely incorrect: import * as klona from 'klona';
import { klona } from 'klona'; I know for a fact that this new module definition works, since it's how DefinitelyTyped defines and ships modules, and I've been using this variant for months now across my projects, with my own & external modules. The previous definition failed when using CommonJS format ( |
It was not. I added a new form of export; I didn't remove the old one.
I don't, because I'm writing a library and enabling that for my library spreads the need to use that setting to my users as well.
Doesn't work with ESM.
That's right. The PR made the latter one correct (in addition to keeping what already exists). |
It's not supposed to.
It is. It's changing the export signature. While
This PR makes them both viable. The |
Why not? I'm building my own library that's also supposed to work for both ESM and CJS consumers, and I am not happy with a solution that requires me to write duplicate code just in order to import packages differently. Don't tell me you would - that's why you created
What's bad about that? It's basically just adding a "feature" (even though that nobody would want to use it, and it can be considered an implementation detail). What would it break? In any case, while I really like this package, the current state of it requires me to keep maintaining a fork. |
I would actually have been fine with keeping this closed as long as the PR lukeed/bundt#3 would have been merged (and this package rebuilt with it), which would allow everyone to use the import they want to use. I'm updating it to resolve the introduced conflicts as we speak. But with the referenced commit from today, a regular default import from TS would unfortunately also be broken. |
The circular reference is (1) circular, (2) affects function identity, and (3) deoptimizes the function itself. Please feel free to send a reproduction of the issue(s) you're having. I've written a dozen libraries (not apps) on top of klona and it works fine as is. As mentioned, only type inference/IntelliSense failed when using On top of that, I've used this definition format a couple dozen times, across modules and libraries, and I know it stands up without a problem. I obviously wouldn't keep doing it if it didn't work. Re: bundt PR. I'll accept the |
Again, check your configuration. This is not true. |
Alright, I have spun up a test repo for this: https://github.com/d-fischer/klona-ts-test Output:
As you can see, the CJS build only works with the require form, and the ESM build works with none. Please recommend a change to the configuration on this repo to make one of these files compile under both configurations. Do not recommend (For the record: |
Fully agree with @d-fischer: forcing people to use |
All you need is Your other examples: // This NOT supposed to work, delete
import * as klona from 'klona';
// This only CAN work with CommonJS
import klona = require('klona'); .. so they're moot examples. Again - if you import the new type definitions file into Effectively, what TS needs to support a dual-format module (with default exports) is this: declare module 'foo' {
function bar(x: string): string;
export default bar;
export = bar;
} But that throws because it doesn't know why two formats exist. // --- We can move from default to |
Again, these two configuration switches are not solutions because they're viral. Essentially, this package is useless for TypeScript library developers that don't want to force their users to use specific configuration that is potentially incompatible with their existing code base. |
I understand that. You're taking TS frustrations out on me, when I'm at the mercy of TS design decisions (as are they now). The Anyway, I've already stated this will be fixed in next major (just not as presented here). Until then, you can continue maintaining your fork, or ship your own // rollup.config.js
import resolve from '@rollup/plugin-node-resolve';
import typescript from 'rollup-plugin-typescript2';
export default {
input: 'src/default.ts',
output: [{
format: 'esm',
file: 'lib/index.mjs',
}, {
format: 'cjs',
file: 'lib/index.js',
interop: false,
}],
external: [
'klona',
],
plugins: [
resolve(),
typescript()
]
}
// tsconfig.json
{
"compilerOptions": {
"rootDir": "src",
"outDir": "lib",
"noEmit": true,
"module": "esnext",
"target": "es5",
"lib": ["esnext"],
"sourceMap": true,
"moduleResolution": "node",
"declaration": true,
"forceConsistentCasingInFileNames": true,
"noImplicitReturns": true,
"importHelpers": true,
"strict": true,
"strictFunctionTypes": false,
"strictPropertyInitialization": false,
"suppressImplicitAnyIndexErrors": true,
"esModuleInterop": true,
"noUnusedLocals": true,
"experimentalDecorators": true,
"downlevelIteration": true
},
"include": ["src"],
"exclude": ["node_modules"]
}
// src/default.ts
import klona from 'klona';
console.log(klona);
// lib/index.js
'use strict';
var klona = require('klona');
console.log(klona);
// lib/index.mjs
import klona from 'klona';
console.log(klona); |
That doesn't quite work this way. If you'd specify both export formats, that would mean that all given entry points export in all given ways. But actually, all given entry points only export in one of the ways, making the definitions invalid for both entry points, because they contain exports that don't actually exist in all possible runtime modules. It's not a TS design issue. You either have to write one type definition and have your code adhere to it in all possible compilation results (which is not the case with the current state of this package), or you have to write one TS code base that compiles to different module formats. I'm trying to do the latter, but as long as any of my dependencies don't do either, they can't work. The only underlying design issue is an ES one. Default exports shouldn't exist. But now they do, and they're incompatible with the usual CommonJS way of importing, and people have to work around that incompatibility if they want to support both CJS and ESM. Rollup has one of these workarounds (it basically lets you import packages that are technically wrong!), but I don't use it because it impairs tree shaking. I'm trying to fix it the other way - building the package correctly from the ground up while still staying compatible with "legacy" importing (both from TS and not). |
@d-fischer can you create a package on npm with proper exports? |
Klona and dequal are both getting 2.0 this week, which includes the export change |
Codecov Report
@@ Coverage Diff @@
## next #17 +/- ##
============================================
- Coverage 100.00% 0.00% -100.00%
============================================
Files 1 1
Lines 38 38
============================================
- Hits 38 0 -38
- Misses 0 38 +38
Continue to review full report at Codecov.
|
Hey @d-fischer, I'm trying to get this PR in to kick-off the 2.0 branch. However, I'm not allowed to push into your repo from my terminal (despite being able to edit files through GitHub UI?). Can you please rebase your branch from |
|
@lukeed also, |
@d-fischer Can you not make this difficult? I'm just trying to add your contribution. Your master (last I checked) is behind & GitHub is preventing me from rectifying anything on my end. The original types file is removed and changes should be applied to new @hakimio I don't think so. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Rebasing doesn't work since the branch was merged into my own master already. I merged instead. The TS definition removal still needs to be undone, probably. |
Ah, the merge reintroduced the "old" definitions. That's definitely wrong. |
Thanks. You can add an extra commit that replaces the contents of your (new) export function klona<T>(input: T): T; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you 👍 Will now officially start the 2.0 work. Appreciate the callout & patience
Should be: export declare function klona<T>(input: T): T; |
* add named export * break: export named function * break(types): export named function * chore: remove `kleur.d.ts` file * fix(merge): put back proper type definition Co-authored-by: Luke Edwards <[email protected]>
This breaks in Typescript 4.7+'s "node16" resolution mode:
The version before this change works fine. |
I'd suggest you create a new issue for that. It's not helpful to comment on a merge request that was merged more than two years ago, especially since your issue relates to a version of TypeScript that didn't even exist then (the current version at the date of merge was 3.9.7). |
This duplicates the default export as a named export.
Why?
It is currently impossible to use this in a TypeScript module that compiles to both CJS and ESM targets from the same source code. This is because of the way default imports are handled.
In a CJS target, only this works (and has the TypeScript compiler complain):
Whereas in an MJS target, only this works:
The respective other one will fail at runtime.
With this PR, this will work for both targets:
The default export is kept for backwards compatibility, although I'd advise to get rid of it in a future major update.
Please note that your build system currently doesn't seem to support this, as building the output files failed for me. I have sent the PR lukeed/bundt#3 to fix this. The future update to that package will need to be incorporated into this PR as well.