vanilla-extract icon indicating copy to clipboard operation
vanilla-extract copied to clipboard

ESM TypeScript Module Resolution breaks sprinkles type definitions

Open davidhousedev opened this issue 2 years ago • 6 comments

Describe the bug

We are building a component library using Vanilla Extract and Sprinkles. We have been using CommonJS module resolution via moduleResolution: 'node' in tsconfig.json. We would like to migrate to ES Module resolution via moduleResolution: 'node16' in tsconfig.json. We are encountering issues with the Sprinkles package where the types generated via ES Module resolution are not specific, when they are when using CommonJS module resolution.

When using moduleResolution: 'node', our type definitions look something like this:

dist/sprinkles.css.d.ts

export declare const sprinkles: import("@vanilla-extract/sprinkles/dist/declarations/src/createSprinkles").SprinklesFn<[{
    conditions: {
        defaultCondition: "mobile";
        conditionNames: ("mobile" | "tablet" | "desktop")[];
    };
    styles: {
        display: {
            values: {
                block: {
                    defaultClass: string;
                    conditions: {
                        mobile: string;
                        tablet: string;
                        desktop: string;
                    };
                };
                flex: {
                    defaultClass: string;
                    conditions: {
                        mobile: string;
                        tablet: string;
                        desktop: string;
                    };
                };
                none: {
                    defaultClass: string;
                    conditions: {
                        mobile: string;
                        tablet: string;
                        desktop: string;
                    };
                };
            };
        };
    // ...
}

However, when we use moduleResolution: 'node16', the type definition looks like this:

dist/sprinkles.css.d.ts

export declare const sprinkles: any;

Reproduction

https://github.com/davidhousedev/vanilla-extract-esm-issue-reproduction

System Info

System:
    OS: macOS 11.6.6
    CPU: (16) x64 Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz
    Memory: 311.74 MB / 64.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 16.15.0 - ~/.nvm/versions/node/v16.15.0/bin/node
    Yarn: 1.22.18 - ~/.nvm/versions/node/v16.15.0/bin/yarn
    npm: 8.5.5 - ~/.nvm/versions/node/v16.15.0/bin/npm
  Browsers:
    Chrome: 102.0.5005.115
    Firefox: 101.0
    Safari: 15.5
  npmPackages:
    @vanilla-extract/sprinkles: ^1.4.1 => 1.4.1 
    @vanilla-extract/vite-plugin: ^3.2.1 => 3.2.1 
    vite: ^2.9.9 => 2.9.13

Used Package Manager

yarn

Logs

No response

Validations

davidhousedev avatar Jun 27 '22 16:06 davidhousedev

Just for what it's worth, I suspect the issue may be that moduleResolution: 'node16' makes use of the package.json exports setting. I don't think the SprinklesFn type is included in your current exports. If that's the case, the declaration generation would not resolve the type, and may default to any.

davidhousedev avatar Jun 27 '22 18:06 davidhousedev

I have a similar issue with moduleResolution: "node16":

src/theme/sprinkles.css.ts(264,14): error TS2742: The inferred type of 'sprinkles' cannot be named without a reference to '../../node_modules/@vanilla-extract/sprinkles/dist/declarations/src/createSprinkles.js'. This is likely not portable. A type annotation is necessary.

mc-petry avatar Jul 10 '22 10:07 mc-petry

Facing the same problem with recipe

image

Edit here is the fix for recipe:

yarn patch-package @vanilla-extract/recipes
diff --git a/node_modules/@vanilla-extract/recipes/dist/declarations/src/index.d.ts b/node_modules/@vanilla-extract/recipes/dist/declarations/src/index.d.ts
index 05baf30..a291410 100644
--- a/node_modules/@vanilla-extract/recipes/dist/declarations/src/index.d.ts
+++ b/node_modules/@vanilla-extract/recipes/dist/declarations/src/index.d.ts
@@ -1,3 +1,3 @@
 import type { PatternOptions, RuntimeFn, VariantGroups } from './types';
-export type { RecipeVariants } from './types';
+export type { RecipeVariants, RuntimeFn } from './types';
 export declare function recipe<Variants extends VariantGroups>(options: PatternOptions<Variants>, debugId?: string): RuntimeFn<Variants>;

Looks like it can resolve with the RuntimeFn exported

image

phil-lgr avatar Jul 25 '22 03:07 phil-lgr

Hi @davidhousedev ,

I've been having a look into this this morning, and I think the issue might be in the vite-plugin-dts plugin you're using to generate the declaration types.

If I change the tsconfig.json like so

- "noEmit": true,
+ "declaration": true,
+ "outDir": "dist"

Then yarn tsc can generate the sprinkles declaration file just fine with "moduleResolution": "node16".

Still doing some looking around, but it looks like TypeScript understands this, and it might be the dts plugin that's mixing something up somewhere.

benjervis avatar Jul 28 '22 01:07 benjervis

Also worth nothing that vite-plugin-dts depends on @microsoft/api-extractor, which depends on "typescript": "~4.6.3", which wouldn't understand "moduleResolution": "node16". You might need the downstream dependencies to catch up here.

benjervis avatar Jul 28 '22 04:07 benjervis

I can confirm that this is still an issue. @phil-lgr's fix does work. RuntimeFn is not seen as an export from where the declaration tries to import it.

image

Highlighting does work before the build, but breaks after it. I suppose it's because the types.d.ts file isn't defined in the exports key on the package.json for the recipes package. This means that defining something that has the RuntimeFn type is only possible through the ReturnType of the recipe function.

Again, adding RuntimeFn as an export to index.d.ts just works.

otaviomad avatar Oct 26 '22 09:10 otaviomad

@davidhousedev @benjervis hey all, just wanted to mention this issue still exists with typescript 4.8.4, @vanilla-extract/sprinkles, tsconfig "node16" module resolution and ... drumroll... pnpm. The combination of these modern tools causes the error:

src/shared/style/IconSprinkles.css.ts:30:14 - error TS2742: The inferred type of 'IconSprinkles' cannot be named without a reference to '../../../node_modules/@vanilla-extract/sprinkles/dist/declarations/src/createSprinkles'. This is likely not portable. A type annotation is necessary.

30 export const IconSprinkles = createSprinkles(ResponsiveIconProperties)

the call to createSprinkles is unable to infer the SprinklesFn type. Also see https://github.com/microsoft/TypeScript/issues/47663 for related reports in other projects using pnpm + tsc + esm.

I do believe similar to the PR https://github.com/vanilla-extract-css/vanilla-extract/pull/890 if you just export the SprinklesFn type, then typescript will be able to find and infer the type.

pkieltyka avatar Nov 08 '22 18:11 pkieltyka

here is a PR with the additional types: https://github.com/vanilla-extract-css/vanilla-extract/pull/907

pkieltyka avatar Nov 09 '22 00:11 pkieltyka

Same Issue

jungpaeng avatar Mar 13 '23 03:03 jungpaeng

solution is to move off vanilla-extract to another system, we’re moving to tailwind On Sep 8, 2023, at 4:03 PM, Cristian Etchebarne @.> wrote: I'm still having this issue with Sprinkles, are there any solutions? I'm using Vite to bundle a component library using these files: // tsconfig.json { "compilerOptions": { "baseUrl": ".", "paths": { "components/": ["src/lib/components/"], "icons/": ["src/lib/icons/"], "icons": ["src/lib/icons/index.ts"], "utils/": ["src/lib/utils/"], "mocks/": ["src/lib/mocks/"], "docs/": ["src/lib/docs/"], "hooks": ["src/lib/hooks/index.ts"], "hooks/": ["src/lib/hooks/"], "shared/": ["src/lib/shared/"], "theme": ["src/lib/theme/index.ts"], "theme/": ["src/lib/theme/"], "types": ["src/lib/types.ts", "node", "vite/client", "vitest/globals"] }, "target": "ESNext", "lib": ["DOM", "DOM.Iterable", "ESNext"], "module": "ESNext", "noImplicitAny": true, "skipLibCheck": true, "emitDeclarationOnly": true, "declaration": true, "declarationDir": "dist", "rootDir": "src", / Bundler mode / "moduleResolution": "node", "allowSyntheticDefaultImports": true, "allowImportingTsExtensions": true, "resolveJsonModule": true, "isolatedModules": true, "jsx": "react-jsx", / Linting / "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "types": [ "vitest/globals", "vitest/importMeta", @./jest-dom", @.*/testing-library__jest-dom" ] }, "include": ["src"], "references": [ { "path": "./tsconfig.node.json" } ] }

// tsconfig.node.json { "compilerOptions": { "composite": true, "skipLibCheck": true, "module": "ESNext", "moduleResolution": "bundler", "allowSyntheticDefaultImports": true }, "include": [ "vite.config.ts" ] }

Even though I don't get explicit errors, when bundling the project my sprinkles type end up being any.

—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you are subscribed to this thread.Message ID: @.***>

pkieltyka avatar Sep 08 '23 20:09 pkieltyka