TypeScript ES6类中implements与extends的选择 接口仅含属性时如何选
核心结论
上述示例代码的User类定义位置,应当填写implements。
extends 与 implements 的适用边界 二者的设计目的完全不同,不存在选择上的模糊地带:
extends是类继承关键字,服务于代码复用需求:使用它时,子类会直接获得父类所有属性、方法的实际实现逻辑,是真的复用现成的代码能力,它的继承源头必须是可实例化的类,不能是纯TS接口。implements是接口实现关键字,服务于结构契约校验需求:使用它时,编译器会检查当前类是否完全匹配接口定义的结构要求,不会继承任何实际的代码实现。不管接口是纯属性、纯方法,还是属性和方法混合,只要是定义了类需要满足的结构规则,就可以用这个关键字。
纯属性接口的选择逻辑
你提到的“接口仅包含属性时不知道怎么选”的场景,判断逻辑非常直接:
- 如果接口的作用是定义「类对外必须具备哪些公开属性、分别是什么类型」,不存在需要复用的实现逻辑,就必须用
implements。哪怕接口一个方法都没有,只要是结构层面的规则,就完全符合implements的适用场景,不存在例外。 - 如果在这里错用
extends,会直接触发TS编译报错:因为UserProps是纯TS接口,编译后不会生成任何可运行的JS实体,根本不存在可以被继承的类结构,TS不支持将纯接口作为extends的继承源。
修正后可直接运行的代码示例:
interface UserProps { name: string, address: string, phone: number, } class User implements UserProps { // 注意:必须在类层面先声明需要实现的三个属性,否则TS会提示属性不存在 name: string; address: string; phone: number; constructor(props: UserProps) { this.name = props.name; this.address = props.address; this.phone = props.phone; } }
常见判断误区
- 不要误以为只有带方法的接口才能用
implements:纯属性的接口同样是有效的结构契约,完全在implements的覆盖范围内。 - 只有当你需要复用一个已经完成实现的类的全部逻辑,在其基础上做功能扩展时,才需要用到
extends。比如已经存在带完整实现的BaseUser类,要在它的基础上给User类增加新的能力,这时候才会写出class User extends BaseUser的代码。
内容的提问来源于stack exchange,提问作者Kyle Fong
相关产品推荐
相关产品推荐

