在 Preact 和 typescript 中使用 web 组件

Sim*_*mon 9 web-component typescript custom-element preact

我在Preact 中使用自定义元素又名 web 组件。问题是 Typescript 抱怨元素没有被定义在- 在这种情况下是一个元素:JSX.IntrinsicElementscheck-box

<div className={styles.option}>
    <check-box checked={this.prefersDarkTheme} ref={this.svgOptions.darkTheme}/>
    <p>Dark theme</p>
</div>
Run Code Online (Sandbox Code Playgroud)

错误信息(省略路径):

ERROR in MyComponent.tsx
[tsl] ERROR in MyComponent.tsx(50,29)
      TS2339: Property 'check-box' does not exist on type 'JSX.IntrinsicElements'.

Run Code Online (Sandbox Code Playgroud)

我遇到了以下可能的解决方案,但不幸的是无法正常工作:

  1. /sf/answers/4021468951/ - 这是一个与问题无关的答案,但它涵盖了我的问题

我尝试将以下内容添加到我的typings.d.ts文件中:

ERROR in MyComponent.tsx
[tsl] ERROR in MyComponent.tsx(50,29)
      TS2339: Property 'check-box' does not exist on type 'JSX.IntrinsicElements'.

Run Code Online (Sandbox Code Playgroud)

我的 IDE 使导入部分变灰,IntrinsicElements这意味着它没有被使用 (?!) 并且无论如何它都不起作用。我仍然收到相同的错误消息。

  1. /sf/answers/3879734491/ - 同样为了反应,我试图将它“转换”为 preact,我得到了与 1 相同的结果。

我什至在squoosh项目中找到了一个由 google 维护的文件,他们在其中执行了以下操作来“填充”支持:

在与组件相同的文件夹中,有一个missing-types.d.ts包含以下内容的文件,基本上与我的设置相同,但使用的是index.ts文件而不是文件,check-bock.ts并且他们使用的是较旧的 TS 版本v3.5.3

import * as Preact from 'preact';

declare global {
    namespace JSX {
        interface IntrinsicElements {
            'check-box': any; // The 'any' just for testing purposes
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我假设他们的构建没有失败,那么它是如何工作的,我如何正确定义自定义元素以在 preact / react 组件中使用它们?

我目前正在使用typescript@v3.8.3preact@10.3.4

Sim*_*mon 5

好吧,我设法使用模块增强来解决它:

declare module 'preact/src/jsx' {
    namespace JSXInternal {

        // We're extending the IntrinsicElements interface which holds a kv-list of
        // available html-tags.
        interface IntrinsicElements {
            'check-box': unknown;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

使用该HTMLAttributes接口,我们可以告诉 JSX 哪些属性可用于我们的自定义元素:

// Your .ts file, e.g. index.ts
declare module 'preact/src/jsx' {
    namespace JSXInternal {
        import HTMLAttributes = JSXInternal.HTMLAttributes;

        interface IntrinsicElements {
            'check-box': HTMLAttributes<CheckBoxElement>;
        }
    }
}

// This interface describes our custom element, holding all its
// available attributes. This should be placed within a .d.ts file.
declare interface CheckBoxElement extends HTMLElement {
    checked: boolean;
}
Run Code Online (Sandbox Code Playgroud)

  • 这就是未来的自己。 (3认同)
  • 哇,是的,我又来了。希望我能多次投票赞成这个答案。 (3认同)

Dom*_*nic 5

以下是要使用的正确属性,否则key例如传入时会出错。

declare global {
  namespace JSX {
    interface IntrinsicElements {
      'xx-element1': React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>; // Normal web component
      'xx-element2': React.DetailedHTMLProps<React.HTMLAttributes<HTMLInputElement>, HTMLInputElement>; // Web component extended from input
    }
  }
}
Run Code Online (Sandbox Code Playgroud)


Mat*_*ley 5

使用 typescript 4.2.3 和 preact 10.5.13,以下是定义带有属性的自定义标签名称的方法:

declare module 'preact' {
    namespace JSX {
        interface IntrinsicElements {
            'overlay-trigger': OverlayTriggerAttributes;
        }
    }
}

interface OverlayTriggerAttributes extends preact.JSX.HTMLAttributes<HTMLElement> {
    placement?: string;
}
Run Code Online (Sandbox Code Playgroud)

差异:

  • 该模块是'preact'(必须引用)。
  • 命名空间是JSX.
  • IntrinsicElements类型是扩展 HTMLAttributes 的接口。
  • 它通过 name 扩展 HTMLAttributes preact.JSX.HTMLAttributes
  • 它提供基本元素类型来HTMLElement填充 props/attrs 中的 eventTarget 类型,例如事件侦听器。如果适用,您也可以添加SVGElement

  • 这适用于 TypeScript 4.3.5 和 Preact 10.5.15,但需要注意的是,我还需要在声明之前“导入 'preact'”。 (2认同)