代码如下,这是一段示例代码
type MenuItem<T extends string> =
{
name: string;
command: T;
}
|
{
name: string;
command: string;
children: Array<{
name: string;
command: T;
}>;
}
type CommandType = 'a' | 'b' | 'c'
const menu: Array<MenuItem<CommandType>> = [];
const result: Array<MenuItem<CommandType>> = [];
for (let s = 0; s < menu.length; s++) {
const level1 = menu[s];
if (level1.children && Array.isArray(level1.children) && level1.children.length > 0) {
const childrenList = level1.children;
const children: MenuItem<string>['children'] = [];
for (let a = 0; a < childrenList.length; a++) {
if (childrenList[a].command) {
children.push({
name: childrenList[a].name,
command: childrenList[a].command
});
}
}
if (children.length > 0) {
result.push({
name: level1.name,
command: level1.command,
children
});
}
} else if (level1.command) {
result.push({
name: level1.name,
command: level1.command
});
}
}
那段for循环是想过滤有效数据。
问题是这段代码ts报错,代码逻辑没问题,问题的根本出在MenuItem的类型定义上,本意是想定义一个二级级联数据MenuItem,之所以使用T extends string而不是直接写为string,是因为在某些交互函数的参数中,希望将代表command的参数定义一个固定的可选数据CommandType。
当有子级数据的时候,关心的是子级数据的command,父级数据的command不希望受到CommandType的制约,随便写字符串都可以;没有子级数据时,关心的是第一级数据的command,这时command希望受到CommandType的制约
现在MenuItem的这种定义方式导致下面的代码ts报错,应该怎么定义MenuItem才能在达到目的的同时ts还不报错呢?
用in运算符来收窄