【问题标题】:Extending react-native-paper components in TypeScript在 TypeScript 中扩展 react-native-paper 组件
【发布时间】:2020-10-13 23:49:03
【问题描述】:

我正在努力正确扩展 react-native-paper 组件。我做错了什么或如何正确做?实际上,我对 Typescript 并不完全陌生,但我一直在努力解决这个问题:

// TextInput.tsx
import React from "react";
import { TextInput as PaperTextInput } from "react-native-paper";
import { TextInputProps } from "react-native-paper/lib/typescript/src/components/TextInput/TextInput";

interface MyTextInputProps extends TextInputProps {}

const MyTextInput: React.FC<MyTextInputProps> = (props) => {
  return <PaperTextInput {...props} />;
};

export default MyTextInput;
// Usage:
<TextInput mode="outlined" style={styles.input} label="Email" />

我得到这个错误:

类型'{ mode: "outlined"; 中缺少属性'theme';风格:{ alignSelf:“伸展”; };标签:字符串; }' 但在 'MyTextInputProps' 类型中是必需的

【问题讨论】:

    标签: reactjs typescript react-native


    【解决方案1】:

    如果您查看 TextInputProps 类/接口的 Typescript 声明,它将有一个非可选的 theme 属性。但是,您在那里的导入看起来很可疑 - 也许只是使用您自己的界面来展示您真正需要的道具?

    摆脱警告的快速解决方案是使用Partial

    interface MyTextInputProps extends Partial<TextInputProps> {}
    

    请注意,这将停止 TS 对任何缺少属性的投诉,但是,无论如何,所有其他属性似乎都是可选的(不知道为什么 theme 不是)。

    【讨论】:

    • 如果我找不到任何其他好的解决方案,我会这样做。我只是想知道是否可以使用原始界面,所以当我想要新的道具(以前没有使用过)时,我不必更新这个组件
    • 在这种情况下您仍然可以使用Partial&lt;T&gt;interface MyTextInputProps extends Partial&lt;TextInputProps&gt; 这将为您提供 IDE 支持,但如果您省略任何属性,则不会出现警告。当然,它也不会强制您提供一些缺少的内容,除非它们在您的自定义界面中声明。
    【解决方案2】:

    看起来TextInputProps 实际上并不是TextInput 的道具类型。 ? 这可能是因为the exported component is wrapped with withTheme()

    export default withTheme(TextInput);
    

    final compiled types 里真的很乱:

    declare const _default: (React.ComponentClass<Pick<TextInputProps, "ref" | "label" | "style" | "children" | "pointerEvents" | "allowFontScaling" | "numberOfLines" | "onLayout" | "onPressIn" | "onPressOut" | "testID" | "nativeID" | "maxFontSizeMultiplier" | "selectionColor" | "textBreakStrategy" | "accessible" | "accessibilityActions" | "accessibilityLabel" | "accessibilityRole" | "accessibilityState" | "accessibilityHint" | "accessibilityValue" | "onAccessibilityAction" | "accessibilityLiveRegion" | "importantForAccessibility" | "accessibilityElementsHidden" | "accessibilityViewIsModal" | "onAccessibilityEscape" | "onAccessibilityTap" | "onMagicTap" | "accessibilityIgnoresInvertColors" | "key" | "hitSlop" | "removeClippedSubviews" | "collapsable" | "needsOffscreenAlphaCompositing" | "renderToHardwareTextureAndroid" | "focusable" | "shouldRasterizeIOS" | "isTVSelectable" | "hasTVPreferredFocus" | "tvParallaxProperties" | "tvParallaxShiftDistanceX" | "tvParallaxShiftDistanceY" | "tvParallaxTiltAngle" | "tvParallaxMagnification" | "onStartShouldSetResponder" | "onMoveShouldSetResponder" | "onResponderEnd" | "onResponderGrant" | "onResponderReject" | "onResponderMove" | "onResponderRelease" | "onResponderStart" | "onResponderTerminationRequest" | "onResponderTerminate" | "onStartShouldSetResponderCapture" | "onMoveShouldSetResponderCapture" | "onTouchStart" | "onTouchMove" | "onTouchEnd" | "onTouchCancel" | "onTouchEndCapture" | "render" | "left" | "right" | "disabled" | "onBlur" | "onFocus" | "multiline" | "value" | "mode" | "error" | "placeholder" | "textAlign" | "textAlignVertical" | "onContentSizeChange" | "onScroll" | "scrollEnabled" | "autoCapitalize" | "autoCorrect" | "autoFocus" | "blurOnSubmit" | "caretHidden" | "contextMenuHidden" | "defaultValue" | "editable" | "keyboardType" | "maxLength" | "onChange" | "onChangeText" | "onEndEditing" | "onSelectionChange" | "onSubmitEditing" | "onTextInput" | "onKeyPress" | "placeholderTextColor" | "returnKeyType" | "secureTextEntry" | "selectTextOnFocus" | "selection" | "inputAccessoryViewID" | "clearButtonMode" | "clearTextOnFocus" | "dataDetectorTypes" | "enablesReturnKeyAutomatically" | "keyboardAppearance" | "passwordRules" | "rejectResponderTermination" | "selectionState" | "spellCheck" | "textContentType" | "autoComplete" | "importantForAutofill" | "disableFullscreenUI" | "inlineImageLeft" | "inlineImagePadding" | "returnKeyLabel" | "underlineColorAndroid" | "showSoftInputOnFocus" | "underlineColor" | "activeUnderlineColor" | "outlineColor" | "activeOutlineColor" | "dense"> & {
        theme?: import("@callstack/react-theme-provider").$DeepPartial<ReactNativePaper.Theme> | undefined;
    }, any> & import("@callstack/react-theme-provider/typings/hoist-non-react-statics").NonReactStatics<(React.ComponentClass<TextInputProps, any> & typeof TextInput) | (React.FunctionComponent<TextInputProps> & typeof TextInput), {}>) | (React.FunctionComponent<Pick<TextInputProps, "ref" | "label" | "style" | "children" | "pointerEvents" | "allowFontScaling" | "numberOfLines" | "onLayout" | "onPressIn" | "onPressOut" | "testID" | "nativeID" | "maxFontSizeMultiplier" | "selectionColor" | "textBreakStrategy" | "accessible" | "accessibilityActions" | "accessibilityLabel" | "accessibilityRole" | "accessibilityState" | "accessibilityHint" | "accessibilityValue" | "onAccessibilityAction" | "accessibilityLiveRegion" | "importantForAccessibility" | "accessibilityElementsHidden" | "accessibilityViewIsModal" | "onAccessibilityEscape" | "onAccessibilityTap" | "onMagicTap" | "accessibilityIgnoresInvertColors" | "key" | "hitSlop" | "removeClippedSubviews" | "collapsable" | "needsOffscreenAlphaCompositing" | "renderToHardwareTextureAndroid" | "focusable" | "shouldRasterizeIOS" | "isTVSelectable" | "hasTVPreferredFocus" | "tvParallaxProperties" | "tvParallaxShiftDistanceX" | "tvParallaxShiftDistanceY" | "tvParallaxTiltAngle" | "tvParallaxMagnification" | "onStartShouldSetResponder" | "onMoveShouldSetResponder" | "onResponderEnd" | "onResponderGrant" | "onResponderReject" | "onResponderMove" | "onResponderRelease" | "onResponderStart" | "onResponderTerminationRequest" | "onResponderTerminate" | "onStartShouldSetResponderCapture" | "onMoveShouldSetResponderCapture" | "onTouchStart" | "onTouchMove" | "onTouchEnd" | "onTouchCancel" | "onTouchEndCapture" | "render" | "left" | "right" | "disabled" | "onBlur" | "onFocus" | "multiline" | "value" | "mode" | "error" | "placeholder" | "textAlign" | "textAlignVertical" | "onContentSizeChange" | "onScroll" | "scrollEnabled" | "autoCapitalize" | "autoCorrect" | "autoFocus" | "blurOnSubmit" | "caretHidden" | "contextMenuHidden" | "defaultValue" | "editable" | "keyboardType" | "maxLength" | "onChange" | "onChangeText" | "onEndEditing" | "onSelectionChange" | "onSubmitEditing" | "onTextInput" | "onKeyPress" | "placeholderTextColor" | "returnKeyType" | "secureTextEntry" | "selectTextOnFocus" | "selection" | "inputAccessoryViewID" | "clearButtonMode" | "clearTextOnFocus" | "dataDetectorTypes" | "enablesReturnKeyAutomatically" | "keyboardAppearance" | "passwordRules" | "rejectResponderTermination" | "selectionState" | "spellCheck" | "textContentType" | "autoComplete" | "importantForAutofill" | "disableFullscreenUI" | "inlineImageLeft" | "inlineImagePadding" | "returnKeyLabel" | "underlineColorAndroid" | "showSoftInputOnFocus" | "underlineColor" | "activeUnderlineColor" | "outlineColor" | "activeOutlineColor" | "dense"> & {
        theme?: import("@callstack/react-theme-provider").$DeepPartial<ReactNativePaper.Theme> | undefined;
    }> & import("@callstack/react-theme-provider/typings/hoist-non-react-statics").NonReactStatics<(React.ComponentClass<TextInputProps, any> & typeof TextInput) | (React.FunctionComponent<TextInputProps> & typeof TextInput), {}>);
    export default _default;
    

    您可以使用React.ComponentProps&lt;typeof TextInput&gt;,而不是TextInputProps。但是因为那不是一个接口,所以你不能extend它进入一个新的接口;您必须改用对象类型。

    // TextInput.tsx
    import React from "react";
    import { TextInput as PaperTextInput } from "react-native-paper";
    
    type MyTextInputProps = React.ComponentProps<typeof PaperTextInput> & {
      // ...
    }
    
    const MyTextInput: React.FC<MyTextInputProps> = (props) => {
      return <PaperTextInput {...props} />;
    };
    
    export default MyTextInput;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-08
      • 2018-03-11
      • 2016-10-07
      • 2020-08-12
      • 2020-11-01
      • 2020-06-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多