-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
TSC throws an error when compiling with "moduleResolution": "NodeNext" #1381
Comments
Thanks for reporting. Can anyone elaborate this issue? How can we declare types for mjs entrypoints? (It looks the same if you import |
I think I find the reason why zustand does not work properly as an esm import. While I was searching for related problems, I bumped into this solved issue: hayes/pothos#597, which was also an esm module resolution problem. The author finally got his package fixed after several pushes and I noticed one of his comments:
and
So I first checked his "main": "./lib/index.js",
"types": "./dts/index.d.ts",
"module": "./esm/index.js",
"exports": {
"import": {
"default": "./esm/index.js"
},
"require": {
"types": "./dts/index.d.ts",
"default": "./lib/index.js"
}
}, And according to this configuration, typescript will use diff ./esm/index.d.ts ./dts/index.d.ts@@ -1,11 +1,11 @@
-import './types/global';
-import SchemaBuilderClass from './builder';
-import type { FieldKind, NormalizeSchemeBuilderOptions, SchemaTypes } from './types';
-export * from './plugins';
-export * from './types';
-export * from './utils';
+import './types/global/index.js';
+import SchemaBuilderClass from './builder.js';
+import type { FieldKind, NormalizeSchemeBuilderOptions, SchemaTypes } from './types/index.js';
+export * from './plugins/index.js';
+export * from './types/index.js';
+export * from './utils/index.js';
declare const SchemaBuilder: {
- new <Types extends Partial<PothosSchemaTypes.UserSchemaTypes> = {}>(options: import("./types").RemoveNeverKeys<PothosSchemaTypes.SchemaBuilderOptions<PothosSchemaTypes.ExtendDefaultTypes<Types>>>): PothosSchemaTypes.SchemaBuilder<PothosSchemaTypes.ExtendDefaultTypes<Types>>;
+ new <Types extends Partial<PothosSchemaTypes.UserSchemaTypes> = {}>(options: import("./types/index.js").RemoveNeverKeys<PothosSchemaTypes.SchemaBuilderOptions<PothosSchemaTypes.ExtendDefaultTypes<Types>>>): PothosSchemaTypes.SchemaBuilder<PothosSchemaTypes.ExtendDefaultTypes<Types>>;
registerPlugin: typeof SchemaBuilderClass.registerPlugin;
allowPluginReRegistration: boolean;
};
@@ -23,10 +23,10 @@ export declare type ObjectFieldBuilder<Types extends SchemaTypes, ParentShape> =
export declare const ObjectFieldBuilder: new <Types extends SchemaTypes, ParentShape>(name: string, builder: SchemaBuilderClass<Types>) => PothosSchemaTypes.ObjectFieldBuilder<Types, ParentShape>;
export declare type InterfaceFieldBuilder<Types extends SchemaTypes, ParentShape> = PothosSchemaTypes.InterfaceFieldBuilder<Types, ParentShape>;
export declare const InterfaceFieldBuilder: new <Types extends SchemaTypes, ParentShape>(name: string, builder: SchemaBuilderClass<Types>) => PothosSchemaTypes.InterfaceFieldBuilder<Types, ParentShape>;
-export declare type InputFieldBuilder<Types extends SchemaTypes, Kind extends 'Arg' | 'InputObject' = 'Arg' | 'InputObject'> = PothosSchemaTypes.InputFieldBuilder<Types, Kind>;
+export declare type InputFieldBuilder<Types extends SchemaTypes, Kind extends "Arg" | "InputObject" = "Arg" | "InputObject"> = PothosSchemaTypes.InputFieldBuilder<Types, Kind>;
export declare const InputFieldBuilder: new <Types extends SchemaTypes, Kind extends "InputObject" | "Arg" = "InputObject" | "Arg">(builder: SchemaBuilderClass<Types>, kind: Kind, typename: string) => PothosSchemaTypes.InputFieldBuilder<Types, Kind>;
export declare type BaseTypeRef = PothosSchemaTypes.BaseTypeRef;
-export declare const BaseTypeRef: new (kind: 'Enum' | 'InputObject' | 'Interface' | 'Object' | 'Scalar' | 'Union', name: string) => PothosSchemaTypes.BaseTypeRef;
+export declare const BaseTypeRef: new (kind: "Enum" | "InputObject" | "Interface" | "Object" | "Scalar" | "Union", name: string) => PothosSchemaTypes.BaseTypeRef;
export declare type EnumRef<T, P = T> = PothosSchemaTypes.EnumRef<T, P>;
export declare const EnumRef: new <T, P = T>(name: string) => PothosSchemaTypes.EnumRef<T, P>;
export declare type InputObjectRef<T> = PothosSchemaTypes.InputObjectRef<T>;
@@ -39,13 +39,13 @@ export declare type ScalarRef<T, U, P = T> = PothosSchemaTypes.ScalarRef<T, U, P
export declare const ScalarRef: new <T, U, P = T>(name: string) => PothosSchemaTypes.ScalarRef<T, U, P>;
export declare type UnionRef<T, P = T> = PothosSchemaTypes.UnionRef<T, P>;
export declare const UnionRef: new <T, P = T>(name: string) => PothosSchemaTypes.UnionRef<T, P>;
-export { default as BuildCache } from './build-cache';
-export { default as BuiltinScalarRef } from './refs/builtin-scalar';
-export { default as FieldRef } from './refs/field';
-export { default as InputTypeRef } from './refs/input';
-export { default as InputFieldRef } from './refs/input-field';
-export { ImplementableInputObjectRef } from './refs/input-object';
-export { ImplementableInterfaceRef } from './refs/interface';
-export { ImplementableObjectRef } from './refs/object';
-export { default as OutputTypeRef } from './refs/output';
-//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
+export { default as BuildCache } from './build-cache.js';
+export { default as BuiltinScalarRef } from './refs/builtin-scalar.js';
+export { default as FieldRef } from './refs/field.js';
+export { default as InputTypeRef } from './refs/input.js';
+export { default as InputFieldRef } from './refs/input-field.js';
+export { ImplementableInputObjectRef } from './refs/input-object.js';
+export { ImplementableInterfaceRef } from './refs/interface.js';
+export { ImplementableObjectRef } from './refs/object.js';
+export { default as OutputTypeRef } from './refs/output.js';
+//# sourceMappingURL=index.d.ts.map And the reason is that typescript doesn't mutate any And that's why this problem occurs in zustand because it only generated cjs typedefs, i.e. no ".js" extensions in the export or import statements: index.d.ts, this affects export * from './vanilla';
export * from './react';
export { default as createStore } from './vanilla';
export { default } from './react'; middleware/devtools.d.ts, this and other middleware typedefs affect import type { StateCreator, StoreApi, StoreMutatorIdentifier } from '../vanilla';
declare module '../vanilla' {
interface StoreMutators<S, A> {
'zustand/devtools': WithDevtools<S>;
}
} I am not familiar with the bundle/build scripts in generating or transforming these files, but I hope the above provided info can help you or other contributors locate the problem and fix it. ❤️ |
@Sec-ant Thanks! Good investigation. |
I think it is caused by the extended declarations in the middleware type files: declare module '../vanilla' {
interface StoreMutators<S, A> {
'zustand/devtools': WithDevtools<S>;
}
} But I'm not sure, because I didn't import any middleware in my example. Maybe typescript will analyze all the type files even if they are not imported? |
@Sec-ant If you have a chance, can you try hand-patch the d.ts files in your local folder (or use |
@dai-shi OK, I made a simple test, and it seems that the .js extension is not the only problem, and hand patching them will not fix it (at least not for vanilla). It seems to be another totally different problem. I still do not fully understand whether it is a Typescript bug or not, but I'll show what I've got so far:
|
I have some promising findings: If I change the "./vanilla": {
"types": "./esm/vanilla.d.mts",
"module": "./esm/vanilla.js",
"import": "./esm/vanilla.mjs",
"default": "./vanilla.js"
}, and add a new file:
As I understand it, the |
Just about package.json: "./vanilla": {
"types": "./vanilla.d.ts",
"module": "./esm/vanilla.js",
"import": {
"types": "./esm/vanilla.d.mts", // trying to apply this only for "import"
"default": "./esm/vanilla.mjs",
},
"default": "./vanilla.js"
}, |
Unfortunately no, TSC will use "./vanilla": {
"import": {
"types": "./esm/vanilla.d.mts",
"default": "./esm/vanilla.mjs"
},
"types": "./vanilla.d.ts",
"module": "./esm/vanilla.js",
"default": "./vanilla.js"
}, |
I think there might be a better way to handle this, we can add a a {
"type": "module"
} and something like this in the toplevel "./vanilla": {
"module": "./esm/vanilla.js",
"import": "./esm/vanilla.js",
"default": "./vanilla.js"
} will work. We can also use the |
We did that once in some project, and there was a problem at that time. So, I would like to avoid it if the "changing the order" hack works. |
Ok, I'm fine with this approach. But if that's the case, I'm concerned that adding ".js" extensions may also break some of the packages. |
Is it ☝️ about adding .js in *.d.mts files? So, in summary, what we need to do is:
Sounds okay? |
Yes, I'm not sure whether this will break other runtime or bundlers. Specifically, what concerns me is this.
Basically yes. But 3 can be tricky if the transformation is applied on cjs type emits after build. And in our case, I think the extension should be |
Good point.
That's great to hear.
Can you quickly check if any of middleware (except for immer) works for you? It's the same as
Yes, for "module" condition.
Ah, now I get it. Yeah, it's safer to keep them. |
Already did that, I use I also made a simple test on react, and I didn't find any problems: 👇 This piece of code will build just fine (with a import React from "react";
import create from "zustand";
import { subscribeWithSelector } from "zustand/middleware";
interface BearState {
bears: number;
}
interface BearControls {
increasePopulation: () => void;
}
const useBearStore = create<BearState & BearControls>()(
subscribeWithSelector((set) => ({
bears: 0,
increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
}))
);
export function BearCounter() {
const bears = useBearStore((state) => state.bears);
return <h1>{bears} around here ...</h1>;
}
export function Controls() {
const increasePopulation = useBearStore((state) => state.increasePopulation);
return <button onClick={increasePopulation}>one up</button>;
} |
Sounds great! |
When I want to import the default
create
function fromzustand/vanilla
while settingNodeNext
for bothmodule
andmoduleResolution
intsconfig.json
, TSC will throw an error:error TS2349: This expression is not callable.
I mentioned this issue in microsoft/TypeScript#50058 (comment). However, according to the reply, this is a zustand problem:
Kindly request a fix on this problem, thanks!
In the meantime, I use
default-import
as a temporary patch.this doesn't work
this works
A minimal repo to reproduce this problem: https://stackblitz.com/edit/node-vj368k?file=src/index.ts
The text was updated successfully, but these errors were encountered: