下面我有E类,它扩展了W。两者都有一个属性喵,它是函数的对象。我想从W中获取功能,并将其扩展到E上。但是,我也想从E的类中访问W的原始函数。我假设我可以通过直接调用super来做到这一点,但它不起作用。

class W {
    meow = {
        woof: () => {
            '2'
        }
    }
}

class E extends W {
    meow = {
        ...super.meow,
        hello: () => {
            return super.meow.woof()
        }
    }
}

const x = new E()

console.log(x.meow.hello())

有什么办法可以使用这种语法?

我正在尝试做的真实世界示例:
class Reads {
    one() {
        return '2'
    }

    byId() {
        return '2'
    }
}

class ReadsProp {
    read = new Reads()
}

class UserReads extends Reads {
    byEmail() {
        return this.one()
    }
}

class UserReadsProp extends ReadsProp {
    read = new UserReads()
}

class UserRepo {
    read = new UserReadsProp().read
}

const userRepo = new UserRepo()

console.log(userRepo.read.byEmail())

最佳答案

介绍

我不会那样做(尽管我想我已经找到了一种强制它工作的方法)。在强制它运行的版本之后,我已经展示了我认为应该怎么做。

(您似乎更喜欢依靠ASI来避免编写分号,因此我在下面进行了说明。)

为什么不起作用

您无法使用的原因是Emeow替换了Wmeow。使用“定义”语义创建属性,因此,在创建E的属性时,将抛弃Wmeow(在评估初始化程序之前),并在要创建的对象上的位置创建Emeowsuper.meow与初始化程序中的this.meow相同,并且值为undefined。禁止传播undefined

使它工作

这是我强制它工作的相当难看的方式:

type PropType<TObj, TProp extends keyof TObj> = TObj[TProp]

class W {
    meow = {
        woof: () => '2'
    }
}

class E extends W {
    // @ts-ignore 2564 (not definitely assigned in ctor -- it is, in the super)
    meow: PropType<W, "meow"> & {
        hello: () => string
    }
    constructor() {
        super()
        // @ts-ignore 2565 (not assigned -- it is, in the super)
        this.meow.hello = () => {
            return this.meow.woof()
        }
    }
}

const x = new E()

console.log(x.meow.hello())

On the playground

如您所见,它涉及消除几个TypeScript错误。这是做什么的:
  • 我只为TypeScript声明了meow:
    喵:PropType和{
    你好:()=>字符串
  • 这样做需要提取Wmeow的类型(因此E的具有woof),这是我通过从this answer使用PropType来完成的:
    type PropType<TObj, TProp extends keyof TObj> = TObj[TProp]
    
  • 然后,由于我们知道W创建了meow,因此我扩展了W的构造函数中创建的E:
    this.meow.hello = () => {
        return this.meow.woof()
    }
    

    如果要添加多个功能,则可以通过Object.assign进行分配。
  • 我还更新了woof,因此它实际上返回了'2',因此我们可以看到hello成功调用了它。

  • 我该怎么办

    我将为meow创建类:
    class WMeow {
        woof() {
            return '2'
        }
    }
    
    class W {
        meow = new WMeow()
    }
    
    class EMeow extends WMeow {
        hello() {
            return this.woof()
        }
    }
    
    class E extends W {
        meow = new EMeow()
    }
    
    const x = new E()
    
    console.log(x.meow.hello())
    

    On the playground

    现在,这不能使meow的方法访问WE实例。您使用箭头功能的事实向我建议,您希望他们可以访问this(WE实例)。

    如果您希望访问,WMeowEMeow都可以接受父实例:
    class WMeow<T extends W> {
        constructor(protected parent: T) {
        }
        woof() {
            this.parent.wmethod()
            return '2'
        }
    }
    
    class W {
        meow = new WMeow<W>(this)
    
        wmethod() {
            console.log("wmethod")
        }
    }
    
    class EMeow<T extends E> extends WMeow<T> {
        hello() {
            this.parent.emethod()
            return this.woof()
        }
    }
    
    class E extends W {
        meow = new EMeow(this)
    
        emethod() {
            console.log("emethod")
        }
    }
    
    const x = new E()
    
    console.log(x.meow.hello())
    

    On the playground

    关于javascript - 扩展和扩展另一类的功能,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59263540/

    10-09 23:33