bounty还有6天到期。回答此问题可获得+250声望奖励。Evanss希望引起更多关注这个问题。
我有不同类型的项目(Item
),它们可以存在于我的状态中的不同级别(Section.items
和subSection.items
)。
我需要根据它们的类型(Str
或Num
)将它们传递给不同的React组件。
下面的代码可以工作,但是它不是理想的数据结构。
type I_Str = {
type: "str";
value: string;
};
type I_Num = {
type: "num";
value: number;
};
type Item = I_Str | I_Num;
type SubSection = {
name: string;
items: Item[];
};
type Section = {
name: string;
items: Item[];
subSection?: SubSection[];
};
type State = {
section: Section[];
};
const state: State = {
section: [
{
name: "Sec1",
items: [
{ type: "str", value: "im a string" },
{ type: "num", value: 1 },
],
subSection: [
{
name: "Sub1",
items: [
{ type: "num", value: 999 },
{ type: "str", value: "sub section string" },
],
},
],
},
],
};
function Str({ item }: { item: I_Str }) {
return <div>Value: {item.value.toUpperCase()}</div>;
}
function Num({ item }: { item: I_Num }) {
return <div>Value: {item.value * 10}</div>;
}
function Items({ items }: { items: Item[] }) {
return (
<div style={{ border: "1px solid blue", padding: 20 }}>
{items
.sort((a, b) => {
if (a.type > b.type) return 1;
if (a.type < b.type) return -1;
return 0;
})
.map((item) => {
if (item.type === "str") return <Str item={item} />;
if (item.type === "num") return <Num item={item} />;
})}
</div>
);
}
function SubSection({ subSection }: { subSection: SubSection }) {
return (
<div>
<div>{subSection.name}</div>
<Items items={subSection.items} />
</div>
);
}
function Section({ section }: { section: Section }) {
return (
<div key={section.name} style={{ border: "1px solid grey", padding: 20 }}>
<div>{section.name}</div>
<Items items={section.items} />
{section.subSection && section.subSection.length > 0
? section.subSection.map((sub) => {
return <SubSection key={sub.name} subSection={sub} />;
})
: null}
</div>
);
}
export default function Page() {
return (
<div>
{state.section.map((section) => {
return <Section key={section.name} section={section} />;
})}
</div>
);
}
它并不理想,因为items
是一个数组,但顺序并不重要。
此外,你应该只能有一个项目的每一种类型,例如这不应该被允许:
items: [
{ type: "str", value: “String 1” },
{ type: "str", value: “String 2” },
]
我可以将Items
更改为对象,然后我对数据结构感到满意,但TypeScript错误:
type Items = {
str?: string;
num?: number;
};
type SubSection = {
name: string;
items: Items;
};
type Section = {
name: string;
items: Items;
subSection?: SubSection[];
};
type State = {
section: Section[];
};
const state: State = {
section: [
{
name: "Sec1",
items: {
str: "Im a st",
num: 1,
},
subSection: [
{
name: "Sub1",
items: {
num: 999,
str: "sub section string",
},
},
],
},
],
};
function Str({ value }: { value: string }) {
return <div>Value: {value.toUpperCase()}</div>;
}
function Num({ value }: { value: number }) {
return <div>Value: {value * 10}</div>;
}
function Items({ items }: { items: Items }) {
return (
<div style={{ border: "1px solid blue", padding: 20 }}>
{["num", "str"].map((key) => {
const value = items[key];
if (!value) return;
if (key === "num") return <Num value={value} />;
if (key === "str") return <Str value={value} />;
})}
</div>
);
}
function SubSection({ subSection }: { subSection: SubSection }) {
return (
<div>
<div>{subSection.name}</div>
<Items items={subSection.items} />
</div>
);
}
function Section({ section }: { section: Section }) {
return (
<div key={section.name} style={{ border: "1px solid grey", padding: 20 }}>
<div>{section.name}</div>
<Items items={section.items} />
{section.subSection && section.subSection.length > 0
? section.subSection.map((sub) => {
return <SubSection key={sub.name} subSection={sub} />;
})
: null}
</div>
);
}
export default function Page() {
return (
<div>
{state.section.map((section) => {
return <Section key={section.name} section={section} />;
})}
</div>
);
}
const value = items[key]; // Error occurs here
TS7053:元素隐式地具有“any”类型,因为类型“string”的表达式不能用于索引类型“Items”。 在类型“Items”上未找到参数类型为“string”的索引签名。
最好的方法是什么?我简化了我的示例代码,实际上我有更多的类型,而不仅仅是str
和num
和它们的值也可以更复杂(例如,变化的对象不仅仅是原始类型)。
3条答案
按热度按时间cfh9epnr1#
我做的第一件事是重命名组件名(为
ItemsComp
),因为您对类型和组件使用了相同的名称。例如:-type Items
和function Items()
我的问题是你有一个动态的类型计数吗?我想不会,因为您已经为每种类型创建了单独的组件。例如:-
function Str()
、function Num()
如果我是对的,你能做这样的事情吗?
这次我不会出错
doinxwow2#
你需要将数组标记为
as const
,否则它就是一个string[]
vhmi4jdf3#
最简单的方法是检查是否定义了每个属性:
注意:显式检查undefined很重要,以免在空字符串或零上短路。
Code Sandbox