Typescript union type not working

I have the following classes:

export interface ISimpleUser {
    id: number;
    full_name: string;
}


export interface IMember extends ng.resource.IResource<IMember> {
    id: number;
    project: number;
    user: number|ISimpleUser;
    skills: ISkill[];
    about: string;
    accepted: Boolean;

    updated: Date;
    created: Date;
}

At some point I want to iterate over the members, as in the following example:

        return angular.forEach<resources.IMember>(this.project.members,
            (member: resources.IMember) => {
                return member.user.id == user.id;
            }).length > 0;

But I get this error:

error TS2339: Property 'id' does not exist on type 'number | ISimpleUser'

I don’t know what exactly is wrong. I see other parts of the code working with connection types.

Thank.

+4
source share
3 answers

To handle this scenario, you need to do some type checking and type casting:

(member: resources.IMember) => {
  return member.user.id == user.id;
  if (typeof (member.user) === 'number') {
    return member.user == user.id;
  } else {
    return (<ISimpleUser>member.user).id == user.id;
  }
}).length > 0;

Just because you know the possible types of code / development time does not mean that compilation code knows the types at runtime. So you can check the type member.userto see if it is a number and then conditionally match.

+4
source

number TypeScript ( JavaScript) id. ( ), . , user :

user: IOtherThing|ISimpleUser;

IOtherThing id, .

, , , - :

var getId = (id: number | IMember) => {
        if (typeof id === "number") {
            return id;
        } else {
            return id.id;
        }
    };
return angular.forEach<resources.IMember>(this.project.members,
    (member: resources.IMember) => {
        return getId(member.user.id) === getId(user);
    }).length > 0;
+2

Typescript doesn't know how to deal with member.userin your foreach, you need to put the logic in a statement typeof if:

return angular.forEach<resources.IMember>(this.project.members, (member: resources.IMember) => {
    var memberUser = member.user;

    if(typeof memberUser === 'number'){
        return memberUser === user.id;
    } else if (typeof member.user === 'object') {
        return memberUser.id === user.id;
    }
}).length > 0;

Using typeofTypeScript, you can specify which type you want to use at which point.

Otherwise, if you know that your list contains only ISimpleUser, you can use member.userievar memberUser = <ISimpleUser> member.user;

+2
source

All Articles