改别人Bug 系列《TS面试题接口规范构造函数》

2022-05-06 17:23:27 浏览数 (2)

今天小孙同学问了一个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 满足代码

代码分析


看代码意思应该是想定义一个接口,FooBar 都实现这个接口,然后函数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,它用传入的类型创建实例。

0 人点赞