今天小孙同学问了一个TS面试题,本以为很简单回答一下,发现一下并不是想象那样。记载一下,还收了他一个大红包,感谢。
项目背景
据说是一个面试,题目是这样的:
代码语言:javascript复制interface MyInterface {
...
}
class Bar implements MyInterface {
constructor(public name: string) {}
}
class Foo implements MyInterface {
constructor(public name: string) {}
}
function myfn(Klass: MyInterface, name: string) {
return new Klass(name);
}
myfn(Bar);
myfn(Foo);
让实现 MyInterface 满足代码
代码分析
看代码意思应该是想定义一个接口,Foo
和 Bar
都实现这个接口,然后函数myfn 第一个参数 Klass (克拉斯哈哈) 可以new 对象,所以接口应该有构造函数。
解决方案
初步想法
最初按照题目和分析,加上构造函数就行,之前我也没有这样用过:
代码语言:javascript复制interface MyInterface {
new (name:string):MyInterface
}
class Bar implements MyInterface {
constructor(public name: string) {}
}
class Foo implements MyInterface {
constructor(public name: string) {}
}
function myfn(Klass: MyInterface, name: string) {
return new Klass(name);
}
let bar = myfn(Bar,'1');
let foo = myfn(Foo,'2');
console.log(bar,foo);
输出结果:
代码语言:javascript复制Bar { name: '1' } Foo { name: '2' }
运行时可以的,但是类型检查室报错的。
TS 推荐写法
代码语言:javascript复制interface MyInterface {
}
interface MyConstructor{
new (name:string):MyInterface
}
class Bar implements MyInterface {
constructor(public name: string) {}
}
class Foo implements MyInterface {
constructor(public name: string) {}
}
function myfn(Klass: MyConstructor, name: string) {
return new Klass(name);
}
let bar = myfn(Bar,'1');
let foo = myfn(Foo,'2');
console.log(bar,foo);
这里因为当一个类实现了一个接口时,只对其实例部分进行类型检查。 constructor存在于类的静态部分,所以不在检查的范围内。
因此,我们应该直接操作类的静态部分。 看下面的例子,我们定义了两个接口, MyConstructor
为构造函数所用和MyInterface
为实例方法所用。 为了方便我们定义一个构造函数 myfn,它用传入的类型创建实例。