You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Stencil组件在React TypeScript项目中类型导出与枚举使用问题

Stencil组件在React+TypeScript项目中的类型识别问题

问题概述

我开发了一个Stencil组件库,在React + TypeScript项目中引入后,组件功能正常,但TypeScript无法识别组件的JSX类型,报错:

Property 'my-comp' does not exist on type 'JSX.IntrinsicElements'.ts(2339)

Stencil构建会在dist/types生成类型文件,但React项目无法自动识别这些类型。我希望不依赖React Integration或@lit/react,通过构建产物自动实现类型导入,而非手动编写声明文件。

现有配置

package.json 类型导出

"types": "dist/types/index.d.ts",
"exports": {
  ".": {
    "import": "./dist/my-components/my-components.esm.js"
  },
  "./my-component": {
    "import": "./dist/components/my-component.js",
    "types": "./dist/components/my-component.d.ts"
  },
  "./loader": {
    "import": "./loader/index.js",
    "types": "./loader/index.d.ts"
  },
  "./styles": "./dist/my-components/my-components.css"
},

Stencil outputTargets 配置

outputTargets: [
  {
    type: "dist",
    esmLoaderPath: "../loader",
  },
  {
    type: "dist-custom-elements",
    customElementsExportBehavior: "auto-define-custom-elements",
    externalRuntime: false,
  },
  {
    type: "docs-readme",
  },
  {
    type: "www",
    serviceWorker: null,
  },
],

尝试过的方案及问题

  1. 手动声明类型:在React项目src下创建components.d.ts可解决类型报错,但无法自动化:

    type IMyComp = {
      name: string;
      size: string;
    }
    declare namespace JSX {
      interface IntrinsicElements {
        'my-comp': IMyComp;
      }
    }
    
  2. 半自动化类型导入:添加以下代码后组件类型识别正常,但使用枚举Size时报错:

    import { Components as MyComponents } from '@myStencilComps/ui/dist';
    
    declare global {
      namespace JSX {
        export interface IntrinsicElements {
          'my-comp': MyComponents.MyComp;
        }
      }
    }
    

    使用组件代码:

    <my-comp
      name="myTest"
      size={Size.Md}
    />
    

    报错信息:

    Uncaught SyntaxError: The requested module '/@fs/Users/../../../ui/dist/my-components/my-components.esm.js' does not provide an export named 'Size' (at App.tsx:8:10)
    

    其中Size是Stencil项目types目录中声明的枚举:

    export enum Size {
      SM = 'sm',
      MD = 'md',
      LG = 'lg',
    }
    
    export default Rounded;
    

解决方案

1. 修复枚举的导出与导入

Stencil不会自动将自定义枚举打包进组件ESM文件,需单独导出:

  • 在Stencil项目的src/index.ts中导出枚举:
    export { Size } from './types/size';
    
  • 在React项目中直接从包根路径导入枚举,而非组件ESM文件:
    import { Size } from '@myStencilComps/ui';
    

2. 自动生成全局JSX类型声明

让Stencil自动生成可被React识别的JSX类型,无需手动编写:

  • 确保Stencil项目tsconfig.json中declaration和declarationMap设为true;
  • 在Stencil项目src下创建global.d.ts,添加以下内容:
    import { Components } from './components';
    
    declare global {
      namespace JSX {
        interface IntrinsicElements extends {
          [key in keyof Components]: Components[key];
        } {}
      }
    }
    
  • 重新构建Stencil项目,dist/types会包含全局JSX类型,React项目安装包后TypeScript会自动识别组件类型。

3. 优化package.json的exports配置

补充根路径的类型映射,确保TypeScript能正确找到类型文件:

"exports": {
  ".": {
    "import": "./dist/my-components/my-components.esm.js",
    "types": "./dist/types/index.d.ts"
  },
  "./my-component": {
    "import": "./dist/components/my-component.js",
    "types": "./dist/components/my-component.d.ts"
  },
  "./loader": {
    "import": "./loader/index.js",
    "types": "./loader/index.d.ts"
  },
  "./styles": "./dist/my-components/my-components.css",
  "./types": "./dist/types/index.d.ts"
},

内容的提问来源于stack exchange,提问作者Angel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 00:41:13