打字稿类型a或类型b

时间:2019-02-22 09:29:45

标签: typescript

我有以下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种解决方案对我来说还不够令人满意...

  1. 我可以在每个位置写信

    (entry as IHistory).timeStamp 
    
  2. 我可以定义例如

    const historyEntry: IHistory = entry as IHistory;
    

还有其他可能的解决方案吗?

2 个答案:

答案 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