javascript 尽管const对象和类型包含索引类型,但Typescript在索引类型上引发错误

slmsl1lt  于 2023-01-29  发布在  Java
关注(0)|答案(1)|浏览(118)

我必须承认我缺少了一些关于TypeScript的知识,但是我无法理解下面的问题。希望有人能给我一些启发。
我有一个函数组件,用于根据其属性显示正确的组件,如下所示:

type PossibleProps =
  {identification: {
      ident: 'ident_1',
      type: 'type_1'
  }} |
  {identification: {
      ident: 'ident_2',
      type: 'type_2'
  }} |
  {identification: {
      ident: 'ident_2',
      type: 'type_3'
  }};

const getComponent:React.FC<PossibleProps> = (props) => {
    const componentArray = {
        ident_1: {
            type_1: "ComponentOne",
        },
        ident_2: {
            type_2: "ComponentTwo",
            type_3: "ComponentThree",
        },
    } as const;

    const Component = componentArray?.[props.identification.ident]?.[props.identification.type] || "ErrorUi";
    return <Component {...props} />;
};
  • 组件名称字符串只是为了保持错误消息的可读性。在实际组件上,当然是导入的组件。*

在我看来,这应该行得通:PossibleProps只包含componentArray中包含的对象,即使不包含某些对象,ErrorUi也会起到作用。
尽管如此,我还是从Typescript收到以下错误消息:

Element implicitly has an 'any' type because expression of type '"type_1" | "type_2" | "type_3"' can't be used to index type '{ readonly type_1: "ComponentOne"; } | { readonly type_2: "ComponentTwo"; readonly type_3: "ComponentThree"; }'.
  Property 'type_1' does not exist on type '{ readonly type_1: "ComponentOne"; } | { readonly type_2: "ComponentTwo"; readonly type_3: "ComponentThree"; }'.ts(7053)

如果有人能帮我找出 typescript 在这里抱怨的原因,我将非常感激。
多谢了!
如前所述,我关于 typescript 的经验是有限的。
我测试了一些东西tho和发现一个工作的方式:

const componentArray = {
        ident_1: {
            type_1: "ComponentOne",
            type_2: "ErrorUi",
            type_3: "ErrorUi",
        },
        ident_2: {
            type_1: "ErrorUi",
            type_2: "ComponentTwo",
            type_3: "ComponentThree",
        },
    } as const;

使用真正的组件和大约50个类型,这些类型被划分为大约30个标识(还有更多),这当然会变得相当庞大,很难阅读,所以我真的很感激不必回到这个实现。

    • 编辑**:我找到了一个可行的解决方案。它不是我最喜欢的,但现在它符合所有的条件。

我保留了一个单独的Object allTypes,它包含了所有可能的类型,并为其分配了ErrorUi,然后我将这些默认类型添加到所有满足typescript的ident对象中,并保持对象的可读性:

const allTypes = {
        type_1: "ErrorUi",
        type_2: "ErrorUi",
        type_3: "ErrorUi",
    } as const;

    const componentArray = {
        ident_1: {
            ... allTypes,
            type_1: "ComponentOne",
        },
        ident_2: {
            ... allTypes,
            type_2: "ComponentTwo",
            type_3: "ComponentThree",
        },
    } as const;

如果有人知道更好的方法,我仍然会感谢你的贡献:)

mccptt67

mccptt671#

尝试另一种方法,通过props请求数据,然后返回正确的组件。
示例:

interface Props {
  variant: “type1” | “type2”
}

const MyComponent = ({variant}: Props => {
  if (variant === “type1”) {
    return <WhateverNeeded />
  }
   …code

}

我相信你的问题是你试图比较对象,这可能不像你期望的那样工作。对象比较不像比较原语那么严格,围绕它的规则可能太模糊了。2一个简单的解决方案也可以是字符串化你的对象,从而"伪造"严格类型。3你想避免这样做,因为你失去了类型安全。将数据转换为用作键的字符串以取消对数据的引用,这在某种程度上违背了TypeScript的目的。
有趣的是,我认为你的问题也可能是你没有正确定义键的类型。尝试在使用后直接使用"as string"将联合类型转换为字符串,类似于"as const"
不能有重叠,在这种情况下,尝试"as unknown as string"

相关问题