Here's my comments on your code.
interface Person {
name : string,
/**
* Because you can have an employee working at multiple offices, they cannot have only one OfficeRoles object.
* The roles relationship should reflect the potential for multiple offices.
*/
roles : OfficeRoles
}
interface OfficeRoles {
roles : OfficeRole[]
office : Office
}
interface OfficeRole {
/**
* This doesn't need to be a function, you could implement a readonly property in the class that's assigned
* when the OfficeRole is created.
*/
getType() : RoleType
}
/**
* The Office object does not include the roles it has, or the employees who currently hold those roles.
*/
interface Office {
name : string
}
/**
* I'd recommend against going with an Enum if the type of roles could be office specific.
*/
enum RoleType {
CLERK,CUSTODIAN,SECURITY
}
let office : Office = { name : "OfficeMax" };
// Does not compile, there is no Role class or interface.
let roles : Role[] = [ new ClerkRole( "John" ) , new SecurityRole(1) ];
let person : Person = { name : "John" , roles : roles };
/**
* No Role interface exists.
* Also, you shouldn't subclass OfficeRole just to provide a different value for {@link getType}, that can be done
* in a constructor.
*/
class ClerkRole implements Role {
private name : string;
constructor( name : string ) {
this.name = name;
}
getType() { return RoleType.CLERK; }
}
class SecurityRole implements Role {
private id : number;
constructor( id : number ) {
this.id = id;
}
getType() { return RoleType.SECURITY; }
}
Here's the direction I'd take it in. This does not include any methods you'd normally have to manage the relationships between employees and roles, nor does it include the classes (they're straightforward). It also doesn't include any methods you'd need to maintain the integrity of your object graph.
/**
* Represents an employee.
* An employee can work at different offices and does not have a relationship with an office beyond having a
* role there, therefore office is not modeled on the employee directly.
*/
interface IEmployee {
name : string
roleAssignments: IAssignedRole[];
}
/**
* An employee can work at multiple offices with different roles, which means a N:N relationship between
* {@link IEmployee} and {@link IRole}.
*/
interface IAssignedRole {
employee: IEmployee;
role: IRole;
}
/**
* Assumes there can be any number of roles for a given office. Each role needs a name and exists for only one office.
*/
interface IRole {
name: string;
office: IOffice;
}
/**
* Represents an office.
*/
interface IOffice {
name: string
/**
* Defines roles permitted for this office.
*/
roles : IRole[];
/**
* Captures the roles assignments for this office.
*/
roleAssignments : IAssignedRole[];
/**
* Provides list of employees by iterating through the role assignments.
*/
readonly employees: ReadonlyArray<IEmployee>;
}
Let me know if you have any questions :)