我想将类引用传递给将创建并返回该类实例的函数。但是,我想根据它实现的接口类型检查传入的类。
accepted answer to 'How does typescript interfaces with construct signatures work?'描述了一种依赖于构造函数签名的结构类型检查的方法。当然,这个问题特定于构造函数签名,所以也许我正在咆哮错误的树,因为在我的例子中:
实现IHappyController
的类不共享相同的构造函数签名。
当不相关接口中的构造函数匹配时,很容易产生误报。
interface IHappyController
{
name:string;
}
interface IHappyControllerConstructable
{
// This constructor is compatible with JoyfulController
new ( name:String, joyfulSong:string, joyfulColor:string ):IHappyController;
// This constructor is compatible with DelightfulController
//new ( name:String, time:Date ):IHappyController;
}
interface ISadController
{
name:string;
reason:string;
}
interface ISadControllerConstructable
{
// This constructor is compatible with DismalController, signature is same as DelightfulController
new ( name:String, time:Date ):ISadController;
}
class JoyfulController implements IHappyController
{
constructor( public name:string, joyfulSong:string, joyfulColor:string )
{
}
}
class DelightfulController implements IHappyController
{
constructor( public name:string, time:Date )
{
}
}
class DismalController implements ISadController
{
reason:string;
constructor( public name:string, time:Date )
{
}
}
// happyMaker should return an instance of the passed class, but only if the instance implements IHappyController
var happyMaker = ( clazz:IHappyControllerConstructable ):IHappyController => {
var instance:IHappyController = ServiceLocator.getByClass( clazz );
return instance;
}
happyMaker(JoyfulController); // Expect Success, it implements IHappyController
happyMaker(DelightfulController); // Expect Success, it implements IHappyController
happyMaker(DismalController); // Expect Error, it implements ISadController
我猜(希望)有一个更简单的解决方案,根本不依赖于I*Constructable
接口。但是happyMaker()
的方法签名应该是什么?
interface IHappyController
{
name:string;
}
interface ISadController
{
name:string;
reason:string;
}
class JoyfulController implements IHappyController
{
constructor( public name:string, joyfulSong:string, joyfulColor:string )
{
}
}
class DelightfulController implements IHappyController
{
constructor( public name:string, time:Date )
{
}
}
class DismalController implements ISadController
{
reason:string;
constructor( public name:string, time:Date )
{
}
}
// happyMaker should return an instance of the passed class, but only if the instance implements IHappyController
var happyMaker = ( clazz:/* WHAT GOES HERE? */ ):IHappyController => {
var instance:IHappyController = ServiceLocator.getByClass( clazz );
return instance;
}
happyMaker(JoyfulController); // Expect Success, it implements IHappyController
happyMaker(DelightfulController); // Expect Success, it implements IHappyController
happyMaker(DismalController); // Expect Error, it implements ISadController
答案 0 :(得分:2)
所写的示例无效,因为ISadController
是IHappyController
的子类型而TypeScript使用结构类型,因此对IHappyController
有效的任何内容都将有效与ISadController
。
如果您调整IHappyController
以使其不是ISadController
的超类型,则可以执行此操作:
interface IHappyController {
happyName: string;
}
interface ISadController {
name:string;
reason:string;
}
class JoyfulController implements IHappyController {
constructor(public happyName:string, joyfulSong:string, joyfulColor:string) { }
}
class DelightfulController implements IHappyController {
constructor(public happyName:string, time:Date) { }
}
class DismalController implements ISadController {
reason:string;
constructor(public name:string, time:Date) { }
}
declare var ServiceLocator;
var happyMaker = <T extends IHappyController>( clazz: { new(...args: any[]): T } ): T => {
var instance = ServiceLocator.getByClass( clazz );
return <T>instance;
}
happyMaker(JoyfulController); // OK
happyMaker(DelightfulController); // OK
happyMaker(DismalController); // Error