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

Preact forwardRef组件JSR TypeScript类型标注问题求助

Preact forwardRef按钮组件JSR类型标注问题解决

问题背景

我基于Preact开发了一个使用forwardRef的按钮组件,在JSR的TypeScript环境中,平台要求公开API的所有符号必须添加明确的类型标注。我尝试给组件返回值指定HTMLButtonElement、JSX.Element或JSX.IntrinsicElements["button"]类型均无效,现附上代码及错误提示,寻求解决方案。

原组件代码

import { forwardRef } from "preact/compat";
import type { ButtonProps } from "./type.ts";
import { useButton } from "./use-button.ts";
import LoadingSpinner from "../../icon/LoadingSpinner.tsx";
import type { JSX } from "preact/jsx-runtime";
import { UseButtonReturn } from "./index.ts";

const Button = forwardRef<HTMLButtonElement, ButtonProps>((props, ref) => {
  const {
    children,
    className,
    isDisabled,
    GetVariantButton,
    isLoading,
    GetButtonProps,
    GetSpinnerProps,
    GetDisabled,
    endContent,
    startContent,
    GetSlot,
    ...otherProps
  } = useButton({ ...props });

  const LoadSpinner = (
    <LoadingSpinner
      className={`${GetSpinnerProps?.className} ${GetSlot.yuzuSpinner}`}
    />
  );

  return (
    <>
      <button
        {...otherProps}
        className={`flex flex-row items-center justify-center gap-2 ${className} ${GetDisabled} ${GetButtonProps.className} ${GetVariantButton} ${GetSlot.yuzuBase} ${GetSlot.yuzuDisabled}`.trim()}
        disabled={isDisabled}
        ref={ref}
      >
        {startContent ? startContent : null}
        {children}
        {endContent ? endContent : null}
        {isLoading ? LoadSpinner : null}
      </button>
    </>
  );
});

export default Button;

无效尝试

我曾尝试给组件函数指定返回值类型,但这种写法不符合语法要求:

// 无效写法
const Button = forwardRef<HTMLButtonElement, ButtonProps>((props, ref): JSX.Element || JSX.IntrinsicElements["button"] => {});

错误提示

Checking for slow types in the public API...
error[missing-explicit-type]: missing explicit type in the public API
   | 
61 | const Button= forwardRef<HTMLButtonElement, ButtonProps>((props,ref) => {
   |       ^^^^^^ 该符号缺少明确的类型标注
   | 
   = hint: 为该符号添加明确的类型标注

  info: 公开API中的所有符号都必须有明确的类型

解决方案

问题核心是JSR要求导出的变量本身必须有显式类型标注,而非仅依赖forwardRef的泛型参数推导。我们需要给Button变量直接指定Preact提供的ComponentWithForwardedRef类型:

  1. 首先导入ComponentWithForwardedRef类型:
import type { ComponentWithForwardedRef } from "preact/compat";
  1. 给Button变量添加显式类型标注:
const Button: ComponentWithForwardedRef<HTMLButtonElement, ButtonProps> = forwardRef<HTMLButtonElement, ButtonProps>((props, ref) => {
  // 组件逻辑保持不变
});

修改后的完整代码

import { forwardRef } from "preact/compat";
import type { ComponentWithForwardedRef } from "preact/compat"; // 新增类型导入
import type { ButtonProps } from "./type.ts";
import { useButton } from "./use-button.ts";
import LoadingSpinner from "../../icon/LoadingSpinner.tsx";
import type { JSX } from "preact/jsx-runtime";
import { UseButtonReturn } from "./index.ts";

// 显式指定Button的类型
const Button: ComponentWithForwardedRef<HTMLButtonElement, ButtonProps> = forwardRef<HTMLButtonElement, ButtonProps>((props, ref) => {
  const {
    children,
    className,
    isDisabled,
    GetVariantButton,
    isLoading,
    GetButtonProps,
    GetSpinnerProps,
    GetDisabled,
    endContent,
    startContent,
    GetSlot,
    ...otherProps
  } = useButton({ ...props });

  const LoadSpinner = (
    <LoadingSpinner
      className={`${GetSpinnerProps?.className} ${GetSlot.yuzuSpinner}`}
    />
  );

  return (
    <>
      <button
        {...otherProps}
        className={`flex flex-row items-center justify-center gap-2 ${className} ${GetDisabled} ${GetButtonProps.className} ${GetVariantButton} ${GetSlot.yuzuBase} ${GetSlot.yuzuDisabled}`.trim()}
        disabled={isDisabled}
        ref={ref}
      >
        {startContent ? startContent : null}
        {children}
        {endContent ? endContent : null}
        {isLoading ? LoadSpinner : null}
      </button>
    </>
  );
});

export default Button;

说明

ComponentWithForwardedRef<RefType, PropsType>是Preact专门为forwardRef组件提供的类型,它准确描述了带转发ref的组件类型,完全符合JSR对公开API类型标注的要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 00:04:53