ค้นหาเว็บไซต์

typescript - อนุญาตให้ซับคลาส override ด้วยคุณสมบัติฟังก์ชันหรือเมธอด


class Foo {
  foo: () => void
}

class Bar extends Foo {
  foo() {}
}

มีวิธีใดที่จะบอก TypeScript ให้อนุญาตตัวอย่างข้างต้นหรือไม่?

สนามเด็กเล่น

คลาส 'Foo' กำหนดสมาชิกอินสแตนซ์เป็นพร็อพเพอร์ตี้ 'foo' แต่คลาสที่สืบทอด 'Bar' กำหนดมันเป็นฟังก์ชันสมาชิกอินสแตนซ์

คำตอบ #1

นั่นเป็นเพราะคุณสามารถเรียกใช้เมธอดของคลาสแม่ได้ แต่ไม่สามารถเรียกสมาชิกอินสแตนซ์ของคลาสแม่ได้

เหตุผลสำหรับเรื่องนั้นคือ วิธีการที่เหมาะสมจะถูกบันทึกไว้ในโพรโทไทป์เชน ในขณะที่ฟังก์ชันสมาชิกจะไม่ถูกบันทึก

class Foo {
    foo() {
        return `Successfully called Foo.foo()`;
    }

    bar = () => {
        return `Successfully called Foo.bar()`;
    }
}

console.log(
    ('foo' in Foo.prototype), // true (methods are correctly inherited)
    ('bar' in Foo.prototype), // false (instance properties are not inherited)
);

ถ้าคุณสมบัติไม่มีอยู่ในโซ่ของคุณสมบัติ การพยายามเรียกใช้งานโดยใช้ super จะทำให้เกิดข้อผิดพลาดขณะรันไทม์

class Bar extends Foo {
    foo = () => {
        return super.foo(); // Good: `foo` is in the prototype chain
    }

    bar = () => {
        return super.bar(); // Runtime error: `bar` is not in the prototype chain
    }
}

สิ่งนี้ทำให้ปลอดภัยในการไปจากเมธอดไปยังคุณสมบัติของอินสแตนซ์ของคลาส (ที่นี่: foo) แต่ไม่สามารถทำในทางกลับกันได้

คำตอบ #2

ทางกลับกันได้รับอนุญาตโดย TypeScript. 👇🏻

class Foo {
  foo() { }
}

class Bar extends Foo {
  foo: () => void
  constructor() {
    super()
    this.foo = () => { }
  }
}

คุณยังสามารถเพิ่มเครื่องหมายขีดล่างหน้าชื่อเมธอดแล้วจึงผูกมันในตัวกำหนดค่า 👇🏻

class Foo {
  foo: () => void
}

class Bar extends Foo {
  constructor() {
    super()
    this.foo = this._foo.bind(this)
  }
  _foo() {}
}

มันคงจะดีถ้า TypeScript ให้คุณทำสิ่งต่อไปนี้ได้:

class Foo {
  foo: () => void
}

class Bar extends Foo {
  constructor() {
    super()
    // TypeScript should see that the method is always bound.
    this.foo = this.foo.bind(this)
  }
  foo() {}
}