首先我们要知道typeof UserType和 UserType是两种不同的类型。
第一个类型typeof UserType 是类构造函数的类型。
第二类UserType是UserType类实例的类型。
在这种情况下,我认为最好使用HashMap数据结构而不是switch。
考虑一下:
abstract class UserType { }
abstract class EmpRoleType extends UserType { }
abstract class ClientRoleType extends UserType { }
class EmpSupport extends EmpRoleType { }
class ClientSupport extends ClientRoleType { }
const ClassMap = {
'EmpSupport': class EmpSupport extends EmpRoleType { },
'ClientSupport': class ClientSupport extends ClientRoleType { }
} as const;
在这种情况下,我们不再需要switch。
现在我们可以定义getUserType函数:
type Values<T> = T[keyof T];
function hasProperty<Obj>(obj: Obj, prop: any): prop is keyof Obj {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
const withMap = <
Key extends PropertyKey,
Klass extends new () => any,
ClassMap extends Record<Key, Klass>
>(
classMap: ClassMap
) => {
return function GetValue<Role extends PropertyKey>(
role: Role
): Values<ClassMap> | null {
if (hasProperty(classMap, role)) {
return classMap[role];
}
return null;
};
};
现在我们定义变量以使用正确的映射访问该函数
const GetUserType = withMap(ClassMap);
现在我们可以通过将字符串传递给函数来获取类类型。
const userType = GetUserType('EmpSupport'); // typeof EmpSupport
注意:如果将键传递给函数,它将返回 null
例如。 GetUserType('bad entry');
如果您想创建GetUserType retuen 值的实例,您需要使用额外的括号
const userType = new (GetUserType('EmpSupport'))(); // EmpSupport
allowPermission 应该是一个 typeguard,写成如下:
function allowParentPermission<Allowed extends typeof UserType>(
AllowParentRole: Allowed,
userRole: unknown
): userRole is InstanceType<Allowed> {
return userRole instanceof AllowParentRole;
}
按照惯例,所有类都应该大写,这就是我写AllowParentRole而不是allowParentRole的原因
完整代码:
abstract class UserType { }
abstract class EmpRoleType extends UserType { }
abstract class ClientRoleType extends UserType { }
class EmpSupport extends EmpRoleType { }
class ClientSupport extends ClientRoleType { }
const ClassMap = {
'EmpSupport': class EmpSupport extends EmpRoleType { },
'ClientSupport': class ClientSupport extends ClientRoleType { }
} as const;
type Values<T> = T[keyof T];
function hasProperty<Obj>(obj: Obj, prop: any): prop is keyof Obj {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
const withMap = <
Key extends PropertyKey,
Klass extends new () => any,
ClassMap extends Record<Key, Klass>
>(
classMap: ClassMap
) => {
return function GetValue<Role extends PropertyKey>(
role: Role
): Values<ClassMap> | null {
if (hasProperty(classMap, role)) {
return classMap[role];
}
return null;
};
};
function allowParentPermission<Allowed extends typeof UserType>(
AllowParentRole: Allowed,
userRole: unknown
): userRole is InstanceType<Allowed> {
return userRole instanceof AllowParentRole;
}
Playground
更新
userRole is - 是type guards 的特殊语法
更新 2
abstract class UserType { }
abstract class EmpRoleType extends UserType { }
abstract class ClientRoleType extends UserType { }
class EmpSupport extends EmpRoleType { }
class ClientSupport extends ClientRoleType { }
const ClassMap = {
'EmpSupport': class EmpSupport extends EmpRoleType { },
'ClientSupport': class ClientSupport extends ClientRoleType { }
} as const;
const hasProperty = <Obj,>(obj: Obj, prop: any)
: prop is keyof Obj =>
Object.prototype.hasOwnProperty.call(obj, prop);
type Values<T> = T[keyof T]
const withMap = <
Key extends PropertyKey,
Klass extends new () => any,
ClassMap extends Record<Key, Klass>
>(classMap: ClassMap) => {
function foo<Role extends PropertyKey>(role: Role): Role extends keyof ClassMap ? ClassMap[Role] : Values<ClassMap> | null
function foo<Role extends PropertyKey>(role: Role): Values<ClassMap> | null {
const storageUserType = localStorage.getItem('any item you want');
if (hasProperty(classMap, storageUserType)) {
return classMap[storageUserType]
}
return null;
}
return foo
}
const getUserType = withMap(ClassMap)
const foo = (str: string) => {
const userType = getUserType(str); // EmpSupport
if (userType) {
const result = new userType()
}
}
const result = getUserType('EmpSupport') // typeof EmpSupport
Playground 2