问题出现
今天同事突然找我帮忙看一下TS继承的问题,我看了一下写法也没问题啊。但是实例里面就是调用不了父类的方法。所以我们一步步排查吧。
TS的类和接口
TS的类可以继承类也可以实现接口。 类和接口怎么区分呢
类是用 class 声明的,定义属性和方法, 子类继承需要用到 extends 关键字, 子类只能继承一个父类 子类中使用 super 关键字来调用父类的构造函数和方法
接口用 interface 声明, 定义, 子类或者子接口实现父类接口需要用 implements 关键字, 一个类可以实现多个接口 接口与接口之间可以是继承关系 接口继承类: 常见的面向对象语言中,接口是不能继承类的,但是在 TypeScript 中却是可以的, 当我们在声明 class Point 时,除了会创建一个名为 Point 的类之外,同时也创建了一个名为 Point 的类型, 我们既可以将 Point 当做一个类来用, 也可以将 Point 当做一个类型来用, 接口继承类的时候,也只会继承它的实例属性和实例方法.
代码bug
最后发现是同事在修改代码的过程中,将实例对象丢失了, 当然就没有父类的方法可以调用了。具体代码如下。
class A {
name: string;
age: string;
getName: () => {
return this.name;
}
}
class B extends A {
nickName: string;
constructor() {
super();
}
}
const getNewData: B = (data: B) => {
const newData = data.map(item => {...item, nickName: 'aaa'})
return newData;
}
// 使用
const operator = (data: B) => {
data.map(item => {
item.getName()
})
}
在使用过程中发现item.getName()
不存在,刚开始以为时继承时写错了,经过一番排查才发现,原来是map的锅, 在第一次组装newData的时候,就已经形成了新的数据结构,不再是B类型的实例对象了,当然用不了实例的父类的方法了。
解决办法
修改map循环, 想要添加属性直接赋值到实例中, 然后再return回去。
const getNewData: B = (data: B) => {
const newData = data.map(item => {
item.nickName = 'aaa';
return item;
})
return newData;
}