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

React Native Paper v4中forwardRef扩展复合组件的TypeScript问题

解决React Native Paper v4中TypeScript结合forwardRef扩展带Icon的TextInput问题

完整正确实现代码

import React, { forwardRef, useTheme } from 'react';
import { View, Text, StyleProp, ViewStyle, TextInput as RNTextInput } from 'react-native';
import { TextInput as RNPInput, TextInputProps, TextInputIconProps } from 'react-native-paper';

// 自定义组件Props:继承RN Paper TextInputProps,移除必填的theme,新增自定义label和容器style
type InputComponentProps = Omit<TextInputProps, 'theme'> & {
  label?: string;
  style?: StyleProp<ViewStyle>;
};

// 正确配置forwardRef泛型:第一个参数是RN原生TextInput实例(RN Paper的TextInput ref指向原生组件),第二个是自定义Props
const InputComponent = forwardRef<RNTextInput, InputComponentProps>(
  ({ label, style, ...rest }, ref) => {
    const theme = useTheme();
    return (
      <View style={style}>
        {label && <Text>{label}</Text>}
        <RNPInput
          mode="outlined"
          outlineColor={theme.colors.backdrop}
          selectionColor={theme.colors.accent}
          ref={ref}
          theme={{ colors: { text: '#000' } }} // 替换为你的实际文本颜色配置
          {...rest}
        />
      </View>
    );
  }
);

// 定义复合组件类型:将基础输入组件与Icon组件类型合并
type TextInputComponent = typeof InputComponent & {
  Icon: typeof RNPInput.Icon;
};

// 赋值并断言类型,确保TypeScript识别复合组件结构
const TextInput = InputComponent as TextInputComponent;
TextInput.Icon = RNPInput.Icon;

export { TextInput };

使用示例

const Test = () => {
  return <TextInput right={<TextInput.Icon name="eye" />} label="测试输入框" />;
};

逐个问题解决说明

1. 复合组件Icon的name prop无法被TypeScript识别

直接用Object.assign挂载Icon时,TypeScript无法自动推断复合组件的完整类型。通过显式定义TextInputComponent类型,将基础组件类型与Icon组件类型合并,再将基础组件断言为该类型,就能让TypeScript正确识别TextInput.Icon的所有Props。

2. 移除// @ts-ignore后的ref类型错误

之前错误地将typeof RNPInput作为forwardRef的第一个泛型参数,但该参数需要的是组件实例类型,而非组件本身的类型。RN Paper的TextInput组件的ref指向原生React Native的TextInput实例,因此将泛型第一个参数改为RNTextInput(从react-native导入的TextInput),就能让ref类型完全匹配,无需忽略类型检查。

3. 移除Omit<TextInputProps, 'theme'>后提示theme必填

RN Paper的TextInputProps中theme是必填项,但你的组件内部已经通过useTheme自定义了theme配置,不需要外部传入。保留Omit<TextInputProps, 'theme'>可以从Props中移除该必填项,避免外部使用时的类型报错。


自定义Icon组件的正确写法

如果需要封装自定义Icon(比如默认设置颜色),只需保证类型继承RN Paper的TextInputIconProps即可:

const CustomIcon = (props: TextInputIconProps) => {
  return <RNPInput.Icon color="green" {...props} />;
};

// 调整复合组件类型为自定义Icon的类型
type TextInputComponent = typeof InputComponent & {
  Icon: typeof CustomIcon;
};

const TextInput = InputComponent as TextInputComponent;
TextInput.Icon = CustomIcon;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 04:42:22