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

Typescript's type aliases are not resolved in Vue components #37

Closed
yankeeinlondon opened this issue Oct 29, 2021 · 10 comments
Closed

Typescript's type aliases are not resolved in Vue components #37

yankeeinlondon opened this issue Oct 29, 2021 · 10 comments
Labels
bug Something isn't working

Comments

@yankeeinlondon
Copy link

In my tsconfig.json file I specify the following path alias:

{
    "paths": {
      "~/*": ["src/*"]
    },
}

And then in a VueJS component I might import a dependencies like so:

import { TrueFalse, icon, isTrue } from "~/components/shared";

image

Vite compiles the source without issue and vite-plugin-dts also creates declaration files but as you can see below, the ~/ type alias is still present in the type which makes it unusable as an exported type file.

2021-10-29_14-53-32 (3)

Historically, when using Rollup directly I have used a combination of the ts-patch npm module and the typescript-transform-paths module:

  • ts-patch - patches Typescript's tsc to allow it to use the Typescript plugin API
  • typescript-transform-paths addresses converting type aliases back to full file paths

With this done, you just add the plugins to your tsconfig.json file like so:

{
    "plugins": [
      // Transform paths in output .js files
      { "transform": "typescript-transform-paths" },

      // Transform paths for declarations files
      { "transform": "typescript-transform-paths", "afterDeclarations": true }
    ]
}

This works and I've never found a way to get TYPES to export using the alias Rollup plugin (which is what ViteJS uses I believe). In any case, I'd really like to run everything in ViteJS and your plugin "almost" works ... hoping we can get path aliases incorporated.

@yankeeinlondon
Copy link
Author

Actually it's funny, my traditional means of doing this is nicer in that all aliases are resolved but considering the .d.ts is a TS file I guess maybe TS's built in aliases should work?

@qmhc
Copy link
Owner

qmhc commented Oct 30, 2021

Would you share your vite.config.ts and tsconfig.ts files?

I think this requires some testing with other plugins.

@yankeeinlondon
Copy link
Author

Hi @qmhc I was just coming back to this issue as I've confirmed that Microsoft has been asked many times about whether .d.ts files should follow path aliases (since they are part of the TS spec) but their position is that it should not follow them and I guess there are likely good performance reasons for this stance. That said, it does make this that much more important to solve for.

The ts-patch approach I've alluded to above does work perfectly when using tsc as the underlying engine for transforms. I use this in dozens of repos for this purpose but unfortunately it doesn't pair well with this plugin at the moment.

I had a look at your deps and i would appear you're passing the DTS generation over to tsup. I think anything from @egoist is worth building around and I've been meaning to use TSUP a lot more rather than rolling my own configuations but I'm not aware of how TSUP works under the hood and how to ensure that tsc's plugin API is enabled properly.

@yankeeinlondon
Copy link
Author

I do wonder if maybe this issue needs to be brought over to TSUP as the actual engine for building the declaration files needs to resolve these path aliases either by some means of it's own or by using the containing repo's instance of tsc (as my instance has been patched to use the Typescript plugin API).

@yankeeinlondon
Copy link
Author

yankeeinlondon commented Nov 22, 2021

Ok I ran TSUP locally in a repo which doesn't have any Vue components (aka, so the Vue loader isn't needed) and it transpiled perfectly down to a single typed file. However, when I then added this plugin to the same repo it created the types not in a single file but rather in a tree structure which mimics where the types are defined:

image

and then in the files which utilize the path alias it fails, as you can see in this screenshot:

image

@yankeeinlondon
Copy link
Author

My configuration files are:

vite.config.ts

import path from "path";
import { defineConfig, UserConfig } from "vite";
import Vue from "@vitejs/plugin-vue";
import WindiCSS from "vite-plugin-windicss";
import Icons from "unplugin-icons/vite";
import IconsResolver from "unplugin-icons/resolver";
import Inspect from "vite-plugin-inspect";
import Components from "unplugin-vue-components/vite";
import PC from "vite-plugin-particle-components";
import dts from "vite-plugin-dts";

export default defineConfig({
  resolve: {
    dedupe: ["vue"],
    alias: {
      "~/": `${path.resolve(__dirname, "src")}/`,
    },
  },
  publicDir: false,
  build: {
    lib: {
      name: "particle-components",
      entry: path.resolve(__dirname, "src/known-components.ts"),
    },
    minify: "esbuild",
    rollupOptions: {
      external: ["vue"],
      output: {
        globals: {
          vue: "Vue",
          router: "VueRouter",
        },
      },
    },
  },

  plugins: [
    Vue(),
    WindiCSS(),
    Components({
      resolvers: [IconsResolver()],
      dts: true,
      extensions: ["vue"],
    }),
    Icons(),
    Inspect(),
    dts(),
    PC(),
  ],
} as UserConfig);

tsconfig.json

{
  "compilerOptions": {
    "module": "es2020",
    "target": "es2020",
    "lib": ["DOM", "ESNext"],
    "strict": true,
    "esModuleInterop": true,
    "incremental": true,
    "skipLibCheck": true,
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "noUnusedLocals": true,
    "strictNullChecks": true,
    "forceConsistentCasingInFileNames": true,

    "baseUrl": ".",
    "declaration": true,
    "outDir": "dist",

    "paths": {
      "~/*": ["src/*"]
    },
    "types": ["vite/client"],
    "plugins": [
      // Transform paths in output .js files
      { "transform": "typescript-transform-paths" },

      // Transform paths for declarations files
      { "transform": "typescript-transform-paths", "afterDeclarations": true }
    ]
  },
  "include": ["src"],
  "exclude": ["dist", "node_modules", "**/*.spec.ts"]
}

@yankeeinlondon
Copy link
Author

I was digging around in your source code and realized that tsup is used to build this plugin but you aren't wrapping it's capabilities into this plugin. Guess that explains why they behave differently 😝

@qmhc
Copy link
Owner

qmhc commented Nov 23, 2021

Thanks for your research first!

This plugin is using ts-morph (you can find it in package.json -> dependencies) to create typescript programs and source files, and using typescript LanguageService to emit output files. Finally it using some regular expressions to further process the .d.ts files in outputs.

After I did some debugging, I found there is a problem in judging whether a path is alias path when alias find (is the key when using key-value config) ends with '/'.

Currently a workaround is to change the alias config in vite.config.ts:

import path from 'path'
import { defineConfig } from 'vite'

export default defineConfig({
  resolve: {
    alias: {
      '~': path.resolve(__dirname, 'src')
    }
  }
}

@yankeeinlondon
Copy link
Author

@qmhc many thanks for looking into this; i'll use the workaround for now. Any sense for when this will be fixed? No pressure, just aware that my own attention is spread quite thinly and want to keep an eye out for it if its relatively soon.

@qmhc qmhc added the bug Something isn't working label Nov 23, 2021
@qmhc qmhc closed this as completed Nov 23, 2021
@yankeeinlondon
Copy link
Author

Great. Many thanks. I did a little reading on ts-morph last night ... looks really useful as my normal experience with AST's has been quite painful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants