我有以下2个界面
interface IComment extends IData {
comment: string;
}
interface IHistory extends IData{
differences: any[];
timeStamp: number;
}
它们都扩展
interface IData {
user: string;
date: Moment | string;
isHistory: boolean;
}
现在解决问题
我有一个包含IComment和IHistory元素的数组。
const data: Array<IHistory | IComment> = [...someHistoryArray, ...someCommentArray]
现在,当我想在数组上映射并且要访问timeStamp
data.map((entry: IHistory | IComment) => {
if(entry.isHistory) {
entry.timeStamp
// TS2339: Property 'timeStamp' does not exist on type 'IHistory | IComment'. Property 'differences' does not exist on type 'IComment'.
} else {
entry.comment
// TS2339: Property 'comment' does not exist on type 'IHistory | IComment'. Property 'comment' does not exist on type 'IHistory'.
}
})
好吧,我发现2种解决方案对我来说还不够令人满意...
我可以在每个位置写信
(entry as IHistory).timeStamp
我可以定义例如
const historyEntry: IHistory = entry as IHistory;
还有其他可能的解决方案吗?
答案 0 :(得分:3)
如果在每个接口中添加特定的定义,则可以将isHistory
用作联合的判别式:
interface IComment extends IData {
comment: string;
isHistory: false;
}
interface IHistory extends IData {
differences: any[];
timeStamp: number;
isHistory: true;
}
interface IData {
user: string;
date: string;
isHistory: boolean;
}
let data: Array<IComment | IHistory>=[]
data.map((entry: IHistory | IComment) => {
if(entry.isHistory === true) {
entry.timeStamp //ok
} else {
entry.comment //ok
}
})
答案 1 :(得分:0)
另一种可能性是使用用户定义的类型防护,即帮助编译器得出参数是否具有特定类型的函数。以下代码应该可以解决您的特定问题-我在更改的位中添加了注释。
interface IComment extends IData {
comment: string;
}
interface IHistory extends IData {
differences: any[];
timeStamp: number;
}
interface IData {
user: string;
date: Moment | string;
isHistory: boolean;
}
const data: Array<IHistory | IComment> = [];
data.map((entry: IHistory | IComment) => {
// Explicitely narrows down the type to IHistory within the block
if (isHistory(entry)) {
// entry.timeStamp
} else {
// entry.comment
}
});
// User-Defined Type Guard
function isHistory(data: IData): data is IHistory {
return data.isHistory;
}
有关详细信息,请参见用户定义的类型防护器中的Advanced Types。