所以Typescript的generics guide
末尾有这段代码class BeeKeeper {
hasMask: boolean = true;
}
class ZooKeeper {
nametag: string = 'abc';
}
class Animal {
numLegs: number = 123;
}
class Bee extends Animal {
keeper: BeeKeeper = new BeeKeeper();
}
class Lion extends Animal {
keeper: ZooKeeper = new ZooKeeper();
}
function createInstance<A extends Animal>(c: new () => A): A {
return new c();
}
createInstance(Lion).keeper.nametag; // typechecks!
createInstance(Bee).keeper.hasMask; // typechecks!
该程序仅创建一些类,然后定义一个方法来创建给定类的实例。但是,当我们尝试与变量c
进行比较时会出现问题。例如,如果我们要检查是否c == Lion
,则Typescript会引发错误(playground link)。任何人都知道在进行类型检查的同时还能进行类型检查的方法吗?
答案 0 :(得分:2)
您可以使用type guards。
它看起来像这样:
type Constructor<T extends {} = {}> = new (...args: any[]) => T;
function typeGuard<T>(o: any, className: Constructor<T>): o is T {
return o === className;
}
function createInstance<A extends Animal>(c: Constructor<A>): A {
if (typeGuard(c, Lion)) {
return new c('Lion initialized')
}
return new c();
}
还请注意Constructor<A>
的用法-您已经提到构造函数将根据类型接收参数-您的实现无法实现,因为构造函数定义未接收任何参数,因此您应该使用Constructor<A>
将任意数量的参数传递给构造函数(由您将正确的参数传递给正确的类型构造函数)。
考虑到所有这些因素,我建议使用一种更清洁,更简单的方法。首先定义可以创建的键和对应类型的映射:
type TypeMap = {
"lion": Lion,
"bee": Bee
}
然后仅创建工厂函数,该函数将在调用时建议可能的参数(“ lion” |“ bee”),如果输入了未知参数,则显示错误,并解析正确的返回类型。
function createSimpleInstance<T extends keyof TypeMap>(c: T): TypeMap[T] {
let instance: Animal;
switch (c) {
case "lion":
instance = new Lion("Lion initialized");
break;
case "bee":
instance = new Bee();
break;
default:
throw new Error("Unknown type");
}
return instance as TypeMap[T];
}
这样做的最大好处是,您可以在createSimpleInstance
中创建Lion
和Bee
的确切实例,这可以帮助您自动完成每个构造函数所需的确切参数。
请参阅playground。
答案 1 :(得分:1)
您可以使用if(c === instanceof Lion)
示例:
class BeeKeeper {
hasMask: boolean = true;
}
class ZooKeeper {
nametag: string = 'abc';
}
class Animal {
numLegs: number = 123;
}
class Bee extends Animal {
keeper: BeeKeeper = new BeeKeeper();
}
class Lion extends Animal {
keeper: ZooKeeper = new ZooKeeper();
}
function createInstance<A extends Animal>(c: new () => A): A {
const newInstance = new c();
if(newInstance instanceof Lion) {
console.log('Im a Lion');
}
return newInstance;
}
createInstance(Lion).keeper.nametag; // typechecks!
createInstance(Bee).keeper.hasMask; // typechecks!
希望这能奏效,并祝您愉快:)
答案 2 :(得分:1)
您尝试过以下吗?
if(c instanceof Lion) {
希望我能正确理解您的问题。
答案 3 :(得分:0)
我正在寻找一种无需创建类实例的方法。
简单有效:
function createInstance<A extends Animal>(c: new () => A): A {
const lion: typeof Lion = Lion;
if (lion.toString() === c.toString()) {
console.log("Lion detected")
}
return new c();
}