Typescript 为什么我会得到“一个”;“类型错误”;这里有错误吗?

Typescript 为什么我会得到“一个”;“类型错误”;这里有错误吗?,typescript,typescript2.0,Typescript,Typescript2.0,我有以下两个类型脚本类: export class AbsenceWithUser { @jsonProperty(Absence) public readonly absence: Absence; @jsonProperty(User) public readonly user: User; constructor(absence: Absence, user: User) { this.absence = absence; this

我有以下两个类型脚本类:

export class AbsenceWithUser {
    @jsonProperty(Absence) public readonly absence: Absence;
    @jsonProperty(User) public readonly user: User;

    constructor(absence: Absence, user: User) {
        this.absence = absence;
        this.user = user;
    }
}

export class Birthday {
    @jsonProperty(MomentDateJson) public readonly birthday: moment.Moment;
    @jsonProperty(User) public readonly user: User;

    constructor(birthday: moment.Moment, user: User) {
        this.birthday = birthday;
        this.user = user;
    }
}
我需要创建一个数组,其中的元素可以是
缺席withuser
生日
的实例。我使用以下方法执行此操作:

private getAllEvents():(AbsenceWithUser|Birthday)[] {
    const absences = this.props.absences as (AbsenceWithUser|Birthday)[];
    const birthdays = this.props.birthdays as (AbsenceWithUser|Birthday)[];
    return absences.concat(birthdays);
}
但是,如果我使用
getAllEvents
创建一个数组,它的元素不会被识别为这两个类的实例。我有以下功能:

private eventToDate(x:AbsenceWithUser | Birthday):Moment {
    if (x instanceof AbsenceWithUser) {
        return x.absence.endDate;
    } else if (x instanceof Birthday) {
        return x.birthday;
    } else {
        throw new Error("Unknown event type, x: " + x);
    }
}
以下代码生成错误“未知事件类型”

我应该如何更改代码,以便在
eventToDate
中区分
缺席与用户
生日

请注意,它不需要是
的instanceof

更新1(2017年10月1日13:27 MSK):

试图将
getEvents
方法更改为:

private getAllEvents():(AbsenceWithUser|Birthday)[] {
    const absences:(AbsenceWithUser|Birthday) = this.props.absences as (AbsenceWithUser|Birthday)[];
    const birthdays:(AbsenceWithUser|Birthday) = this.props.birthdays as (AbsenceWithUser|Birthday)[];
    return absences.concat(birthdays);
}
现在我得到了一些错误,比如
Error:(127,15)TS2322:Type'(缺席用户|生日)[]不能分配给Type'缺席用户|生日'。
类型“(缺席用户|生日)[]”不可分配给类型“生日”。
类型“(缺勤WithUser |生日)[]”中缺少属性“生日”。
在WebStorm中

更新2(13:31 01.10.2017 MSK):我试图创建一个空数组,然后使用
concat
将缺勤和生日数组合并为一个数组。为此,我创建了以下数组:

const a:(AbsenceWithUser|Birthday) = [];
WebStorm报告此错误:
error:(127,15)TS2322:类型“never[]”不可分配给类型“缺席与用户|生日”。类型“从不[]”不可分配给类型“生日”。类型“从不[]”中缺少属性“生日”。

我不知道
从不[]
类型来自哪里

更新3(13:46 01.10.2017 MSK):修复了
getAllEvents
中明显的类型错误

private getAllEvents():(AbsenceWithUser|Birthday)[] {
    const absences:(AbsenceWithUser|Birthday)[] = this.props.absences as (AbsenceWithUser|Birthday)[];
    const birthdays:(AbsenceWithUser|Birthday)[] = this.props.birthdays as (AbsenceWithUser|Birthday)[];
    const allEvents:(AbsenceWithUser|Birthday)[] = absences.concat(birthdays);
    return allEvents;
}
更新4(14:01.10.2017 MSK):

另一次尝试:

export type EventTypes = (AbsenceWithUser|Birthday);

private isEmpty(arr:EventTypes[]):boolean {
    return arr.length === 0;
}

private getAllEvents():EventTypes[] {
    const absences:EventTypes[] = this.props.absences as EventTypes[];
    const birthdays:EventTypes[] = this.props.birthdays as EventTypes[];
    const absencesEmpty:boolean = this.isEmpty(absences);
    const birthdaysEmpty:boolean = this.isEmpty(birthdays)
    if (absencesEmpty && !birthdaysEmpty) {
        return birthdays;
    } else if (absencesEmpty && birthdaysEmpty) {
        return [];
    } else if (!absencesEmpty && !birthdaysEmpty) {
        return absences.concat(birthdays);
    } else if (!absencesEmpty && birthdaysEmpty) {
        return absences;
    }
    return [];
}
更新5(2017年10月1日15:28 MSK):最终版本:

private getAllEvents():EventTypes[] {
    const absences:EventTypes[] = this.props.absences.map(absenceJson => {
        return new AbsenceWithUser(absenceJson.absence, absenceJson.user);
    });
    const birthdays:EventTypes[] = this.props.birthdays.map(birthdayJson => {
        return new Birthday(birthdayJson.birthday, birthdayJson.user);
    });
    const absencesEmpty = this.isEmpty(absences);
    const birthdaysEmpty = this.isEmpty(birthdays);
    if (absencesEmpty && birthdaysEmpty) {
        return [];
    } else if (absencesEmpty && !birthdaysEmpty) {
        return birthdays;
    } else if (!absencesEmpty && birthdaysEmpty) {
        return absences;
    } else {
        return absences.concat(birthdays);
    }
}

请注意,理论上可以使用
Object.assign
,以便将从JSON反序列化的对象转换为Typescript类实例(如果您的环境支持)。

我创建了一个示例,演示如何将特定类型的两个数组合并为一个可以同时包含两种类型的项的数组。您可以使用
instanceof
检查类型

class AbsenceWithUser {
    public readonly when: string;
    public readonly user: string;
}

class Birthday {
    public readonly day: string;
    public readonly user: string;
}

class Test {

    constructor(){
      let absences : AbsenceWithUser[] = [new AbsenceWithUser(), new AbsenceWithUser()]
      let birthdays : Birthday[] = [new Birthday(), new Birthday(), new Birthday()]

      let combined:(AbsenceWithUser | Birthday)[] = this.mergeArrays(absences, birthdays)

      if (combined[0] instanceof Birthday) {
        console.log("we have a birthday")
      } else { 
        console.log("we have an absence")
      }

    }

    private mergeArrays(absences: AbsenceWithUser[], birthdays: Birthday[]): (AbsenceWithUser | Birthday)[] {
        var allEvents : (AbsenceWithUser | Birthday)[] = [...birthdays].concat(...absences);
        return allEvents;
    }
}

我创建了一个示例,演示如何将特定类型的两个数组合并到一个可以包含两种类型的项的数组中。您可以使用
instanceof
检查类型

class AbsenceWithUser {
    public readonly when: string;
    public readonly user: string;
}

class Birthday {
    public readonly day: string;
    public readonly user: string;
}

class Test {

    constructor(){
      let absences : AbsenceWithUser[] = [new AbsenceWithUser(), new AbsenceWithUser()]
      let birthdays : Birthday[] = [new Birthday(), new Birthday(), new Birthday()]

      let combined:(AbsenceWithUser | Birthday)[] = this.mergeArrays(absences, birthdays)

      if (combined[0] instanceof Birthday) {
        console.log("we have a birthday")
      } else { 
        console.log("we have an absence")
      }

    }

    private mergeArrays(absences: AbsenceWithUser[], birthdays: Birthday[]): (AbsenceWithUser | Birthday)[] {
        var allEvents : (AbsenceWithUser | Birthday)[] = [...birthdays].concat(...absences);
        return allEvents;
    }
}

我对TS很陌生,但是你能试着键入常量吗:const absences(AbsenceWithUser | Birthday)[]=this.props.absences;在严格类型语言中,通常不可能使用“as”在向量中强制转换整个集合……需要先定义。。。但我还是一个TS新手,所以不知道这到底是如何进行不同的解析的(如果真的是这样的话)…@joshstrike谢谢你的评论。我尝试了你的建议——见更新1。@这很奇怪——即使创建一个带有
(缺席WithUser |生日)
类型的空数组也不起作用(见更新2)。但你为什么要强制执行呢?
此.props.absences
类型是否不正确?请注意,将道具投射到
(缺席用户|生日)[
不会自动将其转换为正确的类型。数据来自哪里?除非您手动创建类的实例,而不是直接使用反序列化数据,
instanceof
将始终为false。我对TS非常陌生,但您能否尝试键入常量,如:const-absences(AbsenceWithUser | birth)[=this.props.absences;在严格类型语言中,通常不可能使用“as”在向量中强制转换整个集合……需要先定义。。。但我还是一个TS新手,所以不知道这到底是如何进行不同的解析的(如果真的是这样的话)…@joshstrike谢谢你的评论。我尝试了你的建议——见更新1。@这很奇怪——即使创建一个带有
(缺席WithUser |生日)
类型的空数组也不起作用(见更新2)。但你为什么要强制执行呢?
此.props.absences
类型是否不正确?请注意,将道具投射到
(缺席用户|生日)[
不会自动将其转换为正确的类型。数据来自哪里?除非手动创建类的实例,而不是直接使用反序列化数据,
instanceof
将始终为false。