【问题标题】:Typescript: How to define conditional typescript props to access object in React?打字稿:如何定义条件打字稿道具以访问 React 中的对象?
【发布时间】:2021-09-26 01:34:30
【问题描述】:

我正在尝试使用 React 道具作为访问对象的键。根据道具type 是“实心”还是“轮廓”,将决定我使用什么数据。嵌套的“solid”和“outline”对象中的对象键不相同,因此 Typescript 抱怨,因为它说它可能无法访问该键。你如何让打字稿快乐?

代码可以正常工作,但不知道如何消除错误。

const icons = {
  outline: {
    default: "x1",
    icon1: "icon1"
  },
  solid: {
    default: "x2",
    icon2: "icon2"
  }
} as const;

// If type is solid, you can only choose a solid iconName
// If type is outline, you can only choose an outlined iconName
type ConditionalProps =
  | { type: "solid"; iconName: keyof typeof icons.solid }
  | { type: "outline"; iconName: keyof typeof icons.outline };

const App = ({type = "outline", iconName = "default"}: ConditionalProps) => {

  // Typescript doesn't complain here
  const text1 = icons[type];
  // TSERROR: Typescript complains here
  const text2 = icons[type][iconName];

  return (
    <div>
      <h1>The chosen icon is...</h1>
      <h2>{Object.keys(text1)}</h2>
      <h2>{text2}</h2>
    </div>
  );
}

export default App;

打字稿错误是:

// TSERROR
Element implicitly has an 'any' type because expression of type
'"icon2" | "icon1" | "default"' can't be used to index type 
'{ readonly default: "defaultOutline"; readonly icon2: "icon2"; } 
| { readonly default: "defaultSolid"; readonly icon1: "icon1"; }'. 
Property 'icon2' does not exist on type 
'{ readonly default: "defaultOutline"; readonly icon2: "icon2"; } 
| { readonly default: "defaultSolid"; readonly icon1: "icon1"; }'.ts(7053)

Codesandbox Link

【问题讨论】:

    标签: reactjs typescript react-typescript


    【解决方案1】:

    简短的回答:你不能。至少,安全。嗯,有点。

    如果你想有一些类型安全,你首先需要缩小每个案例的联合,像这样:

    function matchIcon(props: ConditionalProps) {
      if (props.type === "outline") {
        return icons[props.type][props.iconName];
      }
    
      if (props.type === "solid") {
        return icons[props.type][props.iconName];
      }
    }
    

    这有点多余,但很安全。

    替代方法是抑制错误,但降低代码的安全性:

      const text2 =
        icons[props.type][
          props.iconName as keyof typeof icons.solid & keyof typeof icons.outline
        ];
    

    因为icons[props.type] 可以同时是icons.outline 和icons.solid,我们需要传递一个同时满足这两种情况的iconName 值。 keyof typeof icons.solid &amp; keyof typeof icons.outline 只是可能值的一个子集,如果同时为 outlinesolid 提供它,它仍然可以工作。我们主要是在对编译器撒谎。

    【讨论】:

    • 感谢您的回复。我尝试了第一个 matchIcon() 解决方案,但除非我遗漏了什么,否则它似乎不起作用。 TS还在抱怨。你可以看到我的代码框链接。我添加了一个名为“matchIcon2.tsx”的新文件
    • 执行export default function App(props: ConditionalProps) { 并将props 传递给matchIcon。一旦你破坏,你就会失去任何与 iconName 相关的类型
    猜你喜欢
    • 1970-01-01
    • 2021-04-30
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    • 2018-12-31
    • 2021-11-06
    • 2019-01-02
    • 1970-01-01
    相关资源
    最近更新 更多