我有一个数组,我想循环,但我有麻烦,因为联合类型。我的问题是我从下面的代码中遗漏了什么,所以visual studio代码没有看到我对该特定数组有第二个可选类型?
class Menu {
// name of the menu
name: string;
// list of the ingredients in this menu
// or a list of submenu with its ingredients
list: string[] | Menu[];
hasSubList?: boolean;
}
...
menu: Menu[];
ngOnInit() {
this.loadMenu();
}
ngAfterContentInit() {
this.print();
}
loadMenu(): void {
this.menu = [
{
name: "toast"
list: [
"slide of bread",
],
},
{
name: "Crumble eggs on taste",
hasSubList: true;
list: [
{
name: "Eggs",
list: [
{
"Eggs",
"pepper",
"a pinch of salt",
}
],
},
{
name: "Toast",
list: [
"a slide of bread"
],
},
],
},
];
}
this print(): void {
for(let i=0; i<this.menu.length;i++){
let item = this.menu[i];
console.log(item.name);
for(let j=0; i<item.list.length; j++){
let list = item.list[j];
if(item.hasSubList) {
// HERE
// console intellsense says
// "property 'list' does not exist on type 'string | Menu'
// "property 'list' does not exist on type 'string'
for(let k=0; k< list.list.length; k++}(
console.log(list.list[k]);
}
} else {
console.log(list);
}
}
回顾一下intellsense显示的信息;
"property 'list' does not exist on type 'string | Menu'
"property 'list' does not exist on type 'string'
为什么没有检查菜单?因为&#39; list&#39;存在类型&#39;菜单&#39;
答案 0 :(得分:2)
由于list[j]
的类型为string | Menu
,因此使用它的代码必须能够处理 字符串或菜单,它不能只处理一个或另一个。我认为您依赖的知识是hasSubList
为真,那么list
始终是菜单列表。如果那是你的意思,那么你可以将item
投射到一个菜单(list as Menu
),不过一般情况下最好避免这样的演员,因为他们限制了多少类型检查器可以捕获代码中的真正错误。
答案 1 :(得分:2)
如@jacobm所述,编译器根据 hasSubList 无法知道联合类型的实际类型。
您必须使用一种方法来区分编译器可以理解的内容。 1这样做的方法是检查项目本身的类型,然后根本不需要 hasSubList 属性。
e.g。
for(let i=0; i<this.menu.length;i++){
let item = this.menu[i];
for(let j=0; i<item.list.length; j++){
let list = item.list[j];
// typeof operator can help discriminate the union type
if(typeof item !== 'string') {
for(let k=0; k< list.list.length; k++}(
console.log(list.list[k]);
}
} else {
console.log(list);
}
}
}
这是使用for..of循环而不是for循环的另一个示例。这可能是一种风格偏好,但我建议在不使用循环索引的情况下使用它们,因为它们更简洁,IMO更易读。
for (let item of menu) {
for (let list of item.list) {
if(item !== 'string') {
for(let childItem of list.list) {
console.log(childItem);
}
} else {
console.log(list);
}
}
}
答案 2 :(得分:2)
消息是由Typescript引起的,因为您将其指定为def remove_punctuation(value):
return re.sub('[!#?]', '', value)
clean_ops = [str.strip, remove_punctuation, str.title]
def clean_strings(strings, ops):
result = []
for value in strings:
for function in ops:
value = function(value)
result.append(value)
return result
print(clean_strings(states, clean_ops))
,因此无法确定要使用的类型。使用强制转换是解决此问题的一种方法。
string | Menu[]