我具有以下界面结构来存储旅行者。
interface Person: {
age: number,
name: string
}
interface TravelersDirectory {
[country: string]: Person[]
}
example:
travelersDirectory = {
'India': [
{
age: 30,
name 'X'
},
{
age: 35,
name 'Y'
},
]
}
通过新更改,我将使旅行者与旅行者目录脱钩 人员和引用将存储在Travelers目录中。新界面将是:
interface Persons extends Array<Person>
但是由于业务需求,travelerDirectory可以保留(到Persons的)索引或Person对象的
示例:
const persons = [
{
age: 30,
name 'X'
},
{
age: 35,
name 'Y'
},
];
const travelersDirectory = [
'India': [
0,
{
age: 35,
name 'Y'
},
]
]
这可能吗?类型(索引和Person对象)可以共存吗?我试图通过对TravellersDirectory界面进行更改来解决问题,但是没有成功。 尝试1:
interface TravelersDirectory {
[country: string]: Person[] | number[]
}
Attempt2:
interface Persons extends Array<Person | number>
interface TravelersDirectory {
[country: string]: Persons
}
我该怎么办?
注意:所使用的数据结构是符号性的,我无法重新设计它。只有通过使用界面才能解决此问题
检查此链接以查找确切的问题https://stackblitz.com/edit/typescript-ypc59j
答案 0 :(得分:0)
问题中的第二次尝试是键入此内容的正确方法,但可以简化为:
interface TravelersDirectory {
[country: string]: Array<Person | number>;
}
经过与OP的反复交流,我发现问题出在其他地方,即这段代码:
function getName(travelersDirectory: TravelersDirectory, country: string, index: number) {
return travelersDirectory[country][index].name;
}
这是因为travelersDictionary[country][index]
可以是Person或数字,因此不能保证属性name
的存在。为了解决这个问题,我们需要防止这种情况,并定义如果travelersDictionary[country][index]
的结果是数字时应该怎么办。为此,我们可以将结果保存到变量中,并使用typeof
来检查结果是否为数字,然后再告诉它如果是Person,将会发生什么情况。
function getName(travelersDirectory: TravelersDirectory, country: string, index: number) {
const person = travelersDirectory[country][index];
if (typeof person === "number") {
// getName was called referencing a number instead of a Person.
// Throw Error? Do nothing? Up to you
throw Error("Can't get name of a number");
} else {
// Typescript is smart enough to understand that the variable `person` can't be a number
// (because we guarded against it in the previous if-expression)
// so now we can do person.name
return person.name;
}
}
Here's a Stackblitz证明了这一点
答案 1 :(得分:-1)
根据您的要求,最简单的解决方案是仅引用TravellersDirectory本身中的可能值:
interface TravelersDirectory {
[country: string]: Array<Person | number>;
}
如果您希望它更容易阅读,也可以使用类型别名:
type PersonID = number;
type Persons = Array<Person | PersonID>;
interface TravelersDirectory {
[country: string]: Persons
}
我个人认为,仅使用ID的类型别名并按如下方式声明目录是最易读的方法:
type PersonID = number;
interface TravelersDirectory {
[country: string]: Array<Person | PersonID>;
}
这还允许您以后将人员ID更改为其他对象(例如对象或字符串),而不是数字(如果需要)。