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

javascript - ไม่สามารถใช้ตัวตกแต่ง ecmascript ใหม่ใน typescript 2.4.2


นี่คือตัวอย่างโค้ดของฉัน:

function enumerable(value: boolean) {
  return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    descriptor.enumerable = value;
  };
}

class A {
  @enumerable(false)
  a: number = 1
  b: number = 2

  myMethod () {}
}

const a = new A()

ไม่ว่าฉันจะพยายามอะไร ฉันก็ได้:

D:(real path removed)/first-try-typescript>tsc --emitDecoratorMetadata --experimentalDecorators decorators.ts
decorators.ts(8,3): error TS1240: Unable to resolve signature of property decorator when called as an expression.

ฉันได้ลองทุกอย่างจากคำแนะนำของคำถามเดียวกันใน Stack Overflow:

  • เพิ่ม emitDecoratorMetadata และ experimentalDecorators ลงใน tsconfig
  • รัน tsc --emitDecoratorMetadata --experimentalDecorators
  • การเพิ่ม :any เพื่อระบุฟังก์ชันตัวตกแต่งที่ส่งค่ากลับ
  • เพิ่มชนิด descriptor: TypedPropertyDescriptor<any>

ฉันมักจะได้รับข้อผิดพลาดนี้ ทั้งในเทอร์มินัลและในคำแนะนำโค้ดของ Webstorm ตัวตกแต่งเมธอด - เหมือนกัน (ดูตัวอย่างด้านล่าง)

function test(target: Object,
              propertyKey: string,
              descriptor: TypedPropertyDescriptor<any>): any {
  return descriptor;
}

class A {
  a: number = 1
  b: number = 2

  @test
  myMethod () {}
}

const a = new A()

โค้ดเวอร์ชันล่าสุดอยู่ที่นี่ - https://github.com/rantiev/first-try-typescript

คำตอบ #1

น่าเสียดายที่ ตัวตกแต่งคุณสมบัติ ไม่สามารถเข้าถึงคำอธิบายคุณสมบัติได้ เนื่องจากคุณสมบัติจะอยู่บน อินสแตนซ์ของคลาส ในขณะที่ตัวตกแต่งจะถูกประเมินก่อนที่อินสแตนซ์ใด ๆ จะมีขึ้น นอกจากนี้ คุณสามารถใช้ลายเซ็นต่อไปนี้สำหรับตัวตกแต่งคุณสมบัติเท่านั้น:

function (target: any, propKey: string | symbol)

ดังนั้นก็ไม่มีคำอธิบายตรงนี้

คุณก็ไม่สามารถทำเพียง Object.defineProperty(target, propKey.toString, { enumerable: false, value: ... }) ได้เช่นกัน เพราะนั่นจะถูกแชร์ไปยังทุกอินสแตนซ์ของคลาสของคุณ กล่าวคือ การตั้งค่าคุณสมบัติในอินสแตนซ์หนึ่งจะรั่วไหลไปยังอินสแตนซ์อื่น

การบรรลุสิ่งที่คุณกำลังทำอยู่นั้นเป็นไปได้ แต่ค่อนข้างซับซ้อน สิ่งที่ผมทำโดยทั่วไปคือ สร้าง getter บนโปรโตไทป์ที่สร้างตัวบรรยายคุณสมบัติที่ต้องการทันที อะไรประมาณนี้:

function enumerable(value: boolean) {
    return function (target: any, propKey: string | symbol) {
        Object.defineProperty(target, propKey, {
            get: function () {
                // In here, 'this' will refer to the class instance.
                Object.defineProperty(this, propKey.toString(), {
                    value: undefined,
                    enumerable: value
                });
            },
            set: function (setValue: any) {
                // In here, 'this' will refer to the class instance.
                Object.defineProperty(this, propKey.toString(), {
                    value: setValue,
                    enumerable: value
                });
            }
        });
    };
}

ฟังก์ชัน get/set แบบ "ภายนอก" จะทำงานเพียงครั้งเดียวเท่านั้น เนื่องจากคุณสมบัติของอินสแตนซ์จะบดบังมันหลังจากที่ตัวระบุคุณสมบัติถูกสร้างบนอินสแตนซ์แล้ว