user553086 user553086 - 1 year ago 60
TypeScript Question

How can a parent class determine which type was passed to a method, based on the subclass?

I'm trying to create subclasses to handle permissions for different areas of an app. Each subclass has a different list of valid actions that they handle, along with various reasons we show if the action is not allowed. I'm trying to define a

method on the parent class to check if a permission is enabled, but I want it to complain if I pass in a string that is not a valid action for the current instance.

I know I can handle this by defining
on each subclass, i.e.
hasPermissions (actionName: UserActions) { ... }
, but I'm hoping to avoid this. Is there a way the parent class can determine which actions are allowed, based on the the current instance?

declare var _;

type TPermission<TAction, TReason> = {
action: TAction;
enabled: boolean;
reason?: TReason;

class Permissions {
constructor(protected permissions) {

hasPermission(actionName) {
let permission = _.find(this.permissions, {
action: actionName

return permission ? permission.enabled : false;

type AdminActions = 'Add User' | 'Delete User';
type AdminReasons = 'MaxUsersReached' | 'CantDeleteAnotherAdmin';
type TAdminPermission = TPermission<AdminActions, AdminReasons>;

class AdminPermissions extends Permissions {
protected permissions: TAdminPermission[];

constructor(permissions: TAdminPermission[]) {

type UserActions = 'Subscribe' | 'Unsubscribe';
type UserReasons = 'AlreadySubscribed' | 'AlreadyUnsubscribed';
type TUserPermission = TPermission<UserActions, UserReasons>;

class UserPermissions extends Permissions {
protected permissions: TUserPermission[];

constructor(permissions: TUserPermission[]) {

let permissions: TUserPermission[] = [
action: 'Subscribe',
enabled: true

let user = new UserPermissions(permissions);

user.hasPermission('Subscribe'); // Valid, should return true
user.hasPermission('Unsubscribe'); // Valid, should return false
user.hasPermission('Add User'); // Invalid permission for UserPermissions, should error

Answer Source

You can make the parent class generic:

class Permissions<T extends string> {

    hasPermission(actionName: T) {

And then:

class AdminPermissions extends Permissions<AdminActions> { ... }

class UserPermissions extends Permissions<UserActions> { ... }

Then the compiler will complain about this:

user.hasPermission('Add User');


Argument of type '"Add User"' is not assignable to parameter of type 'UserActions'

As you wanted.

(code in playground)

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download