TS 开发小程序不能用派生类?解决方案来了

803 阅读2分钟

笔者并不标题党,如果你要用更标准的TS的开发小程序,你一定会遇到这个问题,可能让你在小程序TS化的道理上戛然而止。

先看下社区的问题,点击查看

Update(2019-09-24)

这个问题如果在小程序SDK 2.7.2已经修复了,如果你的受众是基础库大于2.7.2,请忽略这篇文章

简单来说问题是怎么样的

class Parent {}


class Child extends Parent {
    
}

Page(new Child())

运行上面这段代码,在SDK 2.7.2以下的版本会报如下错误。

// error 1
Uncaught TypeError: Cannot assign to read only property 'constructor' of object '#<V>'
    at G (VM63 WAService.js:1)
    at Object.t (VM63 WAService.js:1)
    at mt (VM63 WAService.js:1)
    at Rt (VM63 WAService.js:1)
    at index.ts:8
    at require (VM63 WAService.js:1)
    at <anonymous>:11:7
    at HTMLScriptElement.scriptLoaded (appservice?t=1569326156124:1147)
    at HTMLScriptElement.script.onload (appservice?t=1569326156124:1159)
    
// error 2
Page is not constructed because it is not found.

解决上面问题的方案三个方向

  1. 这种情况发送在派生类里如果没有class Child extends Parent,也不会报这个错,单这不符合预期,限制了开发者使用
  2. 在删除同文件夹的index.jsonusingComponents: {}, 单这不符合实际开发,实际开发项目肯定要引用组件
  3. 聚焦错误本身,看下面源码
    var r = qsa.registerElement(e)
      , o = Object.create(q, {   //  打断点后发现这个 o 就是那个Parent
        constructor: {
            value: V
        }
    });
    qsa.Behavior.prepare(r.behavior);
    var a = r.behavior.methods;  //  打断点后 a 就是那个Child
    for (var i in a)
        o[i] = a[i]; // 在这行报错  说Cannot assign to read only property 'constructor' of object '#<V>'
    return o

不能aconstructor属性赋值给o的只读属性constructor;

那么解决方案就是


class Parent {}


class Child extends Parent {
    
}

const options = new Child();
// @ts-ignore
delete options.__proto__.constuctor

Page(new Child())

这样写能解决问题,但不够优雅。那么优雅的解决方案是


class Parent {
    constructor() {
        // @ts-ignore
        delete this.__proto__.constructor
    }
}


class Child extends Parent {
    // 这里可以不用写 默认也是要调用的
    // 这里显式调用 主要是为了让读者更容易了解
    constructor() {
        super()
    }
}

Page(new Child())

EDN

这样就完美解决了该问题。同时也给大家提供了一种解决问题的思路

  1. 先找出问题的最小代码
  2. 一步一步debug源码,即使压缩了也不要怕
  3. 用最优雅的方式解决问题