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 แบบ "ภายนอก" จะทำงานเพียงครั้งเดียวเท่านั้น เนื่องจากคุณสมบัติของอินสแตนซ์จะบดบังมันหลังจากที่ตัวระบุคุณสมบัติถูกสร้างบนอินสแตนซ์แล้ว
