【踩坑记录】TS实际开发中类和实例的使用

90 阅读2分钟

问题出现

今天同事突然找我帮忙看一下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;
}