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 an arroy of members like 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'
Don't know what is wrong exactly. I see other parts of the code working with the union types.
Thanks.
You will need to do some type checking and casting to handle this scenario:
(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 at code/design time does not mean that the compiles code knows types at run time. So you can check the type of member.user
to see if it is a number then conditionally do your comparison.
Typescript doesn't know how to deal with member.user
in your foreach, you need to put the logic in a typeof if
statement:
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;
By using the typeof
TypeScript can infer which type you want to use at which point.
Alternatively if you know your list only contains ISimpleUser
, then you could cast the member.user
i.e var memberUser = <ISimpleUser> member.user;
The number
type in TypeScript (and JavaScript) doesn't have an id
property. To use a property on a union type without protective type checking (to bust the union type), the properties must have the same name and type. For example if the user
property were defined like this:
user: IOtherThing|ISimpleUser;
and IOtherThing
had an id
property, then it would work.
I am guessing, but you probably will have to do something like this:
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;