TypeScript 错误 7053 - 创建自定义 React 组件,用道具覆盖样式,我如何正确地告诉 TS 类型是什么?

TypeScript Error 7053 - Creating a custom React component that overrides styles with a prop, how do I properly tell TS what the type is?

这是我的自定义组件的代码。得到一个它不喜欢我给 'type' 字符串类型的错误。定义 'type' 的正确方法是什么?我假设我需要为其定义某种类型的对象,但不确定如何去做。

import React from 'react';
import { StyleSheet, Text, Pressable } from 'react-native';

interface Props {
  text: string;
  type?: string;
  onPress: () => void;
}

const CustomButton: React.FC<Props> = ({ onPress, text, type = 'PRIMARY' }) => {
  return (
    <Pressable
      onPress={onPress}
      style={[styles.container, styles[`container_${type}`]]}
    >
      <Text style={[styles.text, styles[`text_${type}`]]}>{text}</Text>
    </Pressable>
  );
};

export default CustomButton;

const styles = StyleSheet.create({
  container: {
    width: '100%',
    padding: 15,
    marginVertical: 5,
    alignItems: 'center',
    borderRadius: 5,
  },
  container_PRIMARY: {
    backgroundColor: '#3B71F3',
  },
  container_TERTIARY: {},
  text: {
    fontWeight: 'bold',
    color: 'white',
  },
  text_TERTIARY: {
    fontWeight: 'normal',
    color: 'gray',
  },
});

由于您尝试为 styles 对象使用动态生成的密钥,TS 会报错,因为 type 属性 是 string 类型,这可以是任何字符串,因此与 styles 对象中的键不匹配。

解决此问题的一种方法是将 type 属性 转换为 keyof typeof styles:

const CustomButton: React.FC<Props> = ({ onPress, text, type = 'PRIMARY' }) => {
  const containerKey = `container_${type}` as keyof typeof styles;
  const textKey = `text_${type}` as keyof typeof styles;

  return (
    <Pressable onPress={onPress} style={[styles.container, styles[containerKey]]}>
      <Text style={[styles.text, styles[textKey]]}>{text}</Text>
    </Pressable>
  );
};

但由于转换不可靠,您还可以将 type 属性 的类型设置为 string literal TS 类型:

type TERTIARY = 'TERTIARY';

interface Props {
  text: string;
  type?: 'PRIMARY' | TERTIARY;
  onPress: () => void;
}

const CustomButton: React.FC<Props> = ({ onPress, text, type = 'PRIMARY' }) => {
  return (
    <Pressable onPress={onPress} style={[styles.container, styles[`container_${type}`]]}>
      {/* An error would still be displayed here since the styles object doesn't have a text_PRIMARY field  */}
      {/* <Text style={[styles.text, styles[`text_${type}`]]}>{text}</Text> */}

      {/* If there's no other option, you could resort to casting */}
      <Text style={[styles.text, styles[`text_${type as TERTIARY}`]]}>{text}</Text>
    </Pressable>
  );
};