Skip to content

tsx components type declaration support #669

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

Open
3 tasks done
pawover opened this issue Aug 2, 2023 · 15 comments
Open
3 tasks done

tsx components type declaration support #669

pawover opened this issue Aug 2, 2023 · 15 comments
Labels
enhancement New feature or request

Comments

@pawover
Copy link

pawover commented Aug 2, 2023

Clear and concise description of the problem

使用如下配置:

import { VantResolver } from 'unplugin-vue-components/resolvers';
import Components from 'unplugin-vue-components/vite';

export const configComponents = () => {
  return Components({
    extensions: ['js', 'jsx', 'ts', 'tsx', 'vue'],
    dts: true,
    resolvers: [VantResolver()],
    include: [/\.vue$/, /\.vue\?vue/, /\.md$/, /\.tsx$/, /\.jsx$/],
  });
};

可以得到一个 components.d.ts:

/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com./vuejs/core/pull/3399
export {}

declare module 'vue' {
  export interface GlobalComponents {
    RouterLink: typeof import('vue-router')['RouterLink']
    RouterView: typeof import('vue-router')['RouterView']
    VanButton: typeof import('vant/es')['Button']
  }
}

然后在 App.tsx 中使用:

export const App = defineComponent(() => {
  return () => (
    <>
      <VanButton type="primary">myButton</VanButton>
      <RouterView />
    </>
  );
});

会得到 ts 报错:
image
但事实上组件是可以工作的:
image

Suggested solution

只需要在 components.d.ts 中添加:

declare global {
   const RouterLink: typeof import('vue-router')['RouterLink']
   const RouterView: typeof import('vue-router')['RouterView']
   const VanButton: typeof import('vant/es')['Button']
}

就可以消除报错:
image

所以,可否在生成类型声明时额外添加全局声明以支持 tsx 组件?
虽然 unplugin-auto-import 可以做到这点,但是因为已经有了 xxxResolver 感觉还是更符合知觉一点。

或者如果有现成的解决方案的话请告诉我,谢谢!

Alternative

No response

Additional context

No response

Validations

@pawover pawover added the enhancement New feature or request label Aug 2, 2023
@lishaobos
Copy link
Contributor

这样设置试试: dts: 'src/components.d.ts',

@pawover
Copy link
Author

pawover commented Aug 3, 2023

这样设置试试: dts: 'src/components.d.ts',

还是一样的,你是说把文件加入 tsconfig 吗,现在这样配置应该可以识别,但仅限 SFC
image

@lishaobos
Copy link
Contributor

麻烦提供个 git 仓库,我看下

@pawover
Copy link
Author

pawover commented Aug 4, 2023

麻烦提供个 git 仓库,我看下

https://github.com./Handpear/unplugin-vue-components-test

@a382775086
Copy link

使用vue文件自动引入tsx组件时,在生产环境下会导致组件解析失败,似乎需要主动声明才行
image

@lishaobos
Copy link
Contributor

你这个确认,其他非 tsx 组件的类型都生效了吗

@a382775086
Copy link

不光是tsx组件需要主动声明,其他使用过tsx组件的vue组件 似乎也需要主动声明,目前来看应该是这样的,没找到解决办法
image

@lishaobos
Copy link
Contributor

我的意思是,除去 tsx 组件,纯 vue 的类型有生效吗,如果都没有,可以提供一个 git 仓库

@a382775086
Copy link

除去tsx是生效的

@lishaobos
Copy link
Contributor

那你提个 issue,帮忙提供个简单的 git 仓库,我看下

@eiinu
Copy link

eiinu commented Mar 8, 2024

遇到了同样的问题。
unplugin-vue-components 能够识别 tsx 中使用的 VanButton 组件,代码运行没有问题,样式也可以自动引入。

但是它生成的下面这种方式的 vue 全局组件类型,在 tsx 中不能生效,没有类型提示。

declare module 'vue' {
  export interface GlobalComponents {
    VanButton: typeof import('vant/es')['Button']
  }
}

@whaaaley
Copy link

I reached same conclusion as OP. We need a global declaration option please.

@a382775086
Copy link

a382775086 commented Oct 20, 2024 via email

@whaaaley
Copy link

whaaaley commented Oct 21, 2024

Gross workaround. Works great though. Use script with vite-plugin-watch.

Save in project root fix-components-dts.js

import fs from 'node:fs/promises'

const template = constants => [
  'export {}\ndeclare global {',
  '  ' + constants.join('\n  '),
  '}\n'
].join('\n')

const fixComponentsDts = async ({ source, target }) => {
  const fileContent = await fs.readFile(source, 'utf-8')
  const constants = []

  const typeImportRegex = /(\w+):\s*typeof\s*import\(['"]([^'"]+)['"]\)\['(\w+)'\]/g
  fileContent.replace(typeImportRegex, (_, p1, p2, p3) => {
    constants.push(`const ${p1}: typeof import('${p2}')['${p3}']`)
  })

  await fs.writeFile(target, template(constants))
  console.log(`Fixed ${source} and saved as ${target}`)
}

await fixComponentsDts({
  source: './components.d.ts',
  target: './components-global.d.ts'
})

Add to vite.config.js

// Workaround until this pr is merged:
// https://github.com./unplugin/unplugin-vue-components/pull/673
watch({
  pattern: './components.d.ts',
  command: 'node ./fix-components-dts.js'
})

Add to jsconfig/tsconfig

  "include": [
    "./src/**/*",
    "./auto-imports.d.ts",
    "./components-global.d.ts",
  ],

Output

export {}
declare global {
  const AuthLayout: typeof import('./src/layouts/AuthLayout.jsx')['default']
  ...
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

5 participants