typescript 静态属性名称类型与接口上的动态属性名称冲突[重复]

jq6vz3qz  于 2023-01-06  发布在  TypeScript
关注(0)|答案(2)|浏览(210)

此问题在此处已有答案

How to define Typescript type as a dictionary of strings but with one numeric "id" property(3个答案)
昨天关门了。
我有一个相当简单的接口Item,它被分配给对象。
此接口指定这些对象中的每一个 * 必须 * 具有一个itemName属性集,但如果需要,它们也可以具有带有动态名称的 * 附加 * 属性。
我尝试使用以下代码来实现此功能

interface ItemProperty {
    foo: string;
    bar: string;
}
interface Item {
    itemName: string;
    [propertyName: string]: ItemProperty;
}

现在,显然这会抛出以下错误:
类型为“string”的属性“itemName”不能分配给“string”索引类型“ItemProperty”。
由于itemName在技术上是ItemProperty的一部分,但它是string而不是ItemProperty
如何重写这个值,以便可以设置itemName,而 * 无需 * 满足ItemProperty
最终的Item对象可能如下所示:

const item: Item = {
    itemName: "Item 1",
    dynamicProperty1: {
        foo: "foo",
        bar: "bar"
    }
};
cvxl0en2

cvxl0en21#

相反,您可以使用如下类型联合来解决此问题:

type Item = {
    [propertyName: string]: ItemProperty
} | {itemName: string}

在这里,您可以接受字符串类型或对象

interface ItemProperty {
    foo: string;
    bar: string;
}

type Item = {
    [propertyName: string]: ItemProperty
} | {itemName: string}

const a: Item = {
    itemName: 'something', // works
    a: {
        bar: 'a',
        foo: 'c'
    }, // works
    b: 'something else' // error: the key is not 'itemName'
}

打字机Playground

f1tvaqid

f1tvaqid2#

对于以下接口:

interface Item {
   itemName: string;
    [propertyName: string]: ItemProperty;
}

TS将尝试查找属性的定义。如果找到,它将强制执行该定义。如果没有,它将使用动态定义。
一个简单的解决方案是更新itemName的类型定义以接受多个类型

interface Item {
   itemName: string | ItemProperty;
   [propertyName: string]: ItemProperty;
}

相关问题