TypeScript에서 생성자를 데코레이터로 올바르게 감싸는 방법
클래스를 장식자로 묶는 프로세스로 인해 슈퍼클래스는 해당 클래스의 속성에 액세스할 수 없습니다.왜요?
다음과 같은 코드가 있습니다.
- 클래스의 생성자를 동일한 작업을 수행해야 하는 새 생성자로 대체하는 장식자를 만듭니다.
- 속성을 사용하여 기본 클래스를 만듭니다.
- 기본 클래스를 래핑 장식기로 래핑합니다.
- 기본 클래스를 확장하는 클래스를 만듭니다.
- 확장 클래스의 속성에 액세스하려고 합니다.이것이 실패하는 부분입니다.
코드는 다음과 같습니다.
function wrap(target: any) {
// the new constructor
var f: any = function (...args) {
return new target();
}
f.prototype = target.prototype;
return f;
}
@wrap
class Base {
prop: number = 5;
}
class Extended extends Base {
constructor() {
super()
}
}
var a = new Extended()
console.log(new Extended().prop) // I'm expecting 5 here, but I get undefined.
저는 이것이 일반적인 프로토타입의 뉘앙스이거나 제가 이해하지 못하는 TypeScript의 구체적인 처리 방식이라고 확신합니다.
이는 최신 TS(3.2.4)를 사용하는 보다 현대적인 접근 방식입니다.또한 아래에서는 데코레이터 팩토리 패턴을 사용하여 속성을 전달할 수 있습니다.
function DecoratorName(attr: any) {
return function _DecoratorName<T extends {new(...args: any[]): {}}>(constr: T){
return class extends constr {
constructor(...args: any[]) {
super(...args)
console.log('Did something after the original constructor!')
console.log('Here is my attribute!', attr.attrName)
}
}
}
}
자세한 내용은 여기를 참조하십시오. https://www.typescriptlang.org/docs/handbook/decorators.html#class-decorators
이 코드는 저에게 적합합니다.
function logClass(target: any) {
// save a reference to the original constructor
var original = target;
// the new constructor behaviour
var f : any = function (...args) {
console.log("New: " + original.name);
//return original.apply(this, args);
return new original(...args); // according the comments
}
// copy prototype so intanceof operator still works
f.prototype = original.prototype;
// return new constructor (will override original)
return f;
}
@logClass
class Base {
prop: number = 5;
}
class Extended extends Base {
constructor() {
super()
}
}
var b = new Base()
console.log(b.prop)
var a = new Extended()
console.log(a.prop)
ES2015 Proxy를 사용하여 생성자를 재정의하는 솔루션:
function wrap(target: any) {
return new Proxy(target, {
construct(clz, args) {
console.log(`Constructing ${target.name}`);
return Reflect.construct(clz, args);
}
});
}
@wrap
class Base {
prop: number = 5;
}
class Extended extends Base {
constructor() {
super()
}
}
var a = new Extended()
console.log(new Extended().prop);
StackBlitz에서도 실행할 수 있습니다.
다른 답변의 댓글들은 코드가 작동하지 않는다고 불평합니다.
사실, 효과는 있지만, jsFiddle에서는...
jsFiddle의 코드 생성과 관련된 문제입니다(오래된 버전의 TypeScript 사용).
위의 코드는 TypeScript 2.7.2(Node와 함께 실행)와 함께 작동합니다.
그래서 이것은 기본적으로 Pablorsk의 답변에 있는 코드입니다(인스턴스를 반환할 필요가 없다는 것을 제외하고), 저는 더 엄격한 TSLint를 만족시키기 위해 전체 유형을 추가했습니다...
function logClass<T extends { new(...args: any[]): {} }>(): any {
type Ctor = new (...args: any[]) => T;
return (target: T): Ctor => {
// Save a reference to the original constructor
const Original = target;
// the new constructor behaviour
let decoratedConstructor: any = function (...args: any[]): void {
console.log("Before construction:", Original);
Original.apply(this, args);
console.log("After construction");
};
// Copy prototype so intanceof operator still works
decoratedConstructor.prototype = Original.prototype;
// Copy static members too
Object.keys(Original).forEach((name: string) => { decoratedConstructor[name] = (<any>Original)[name]; });
// Return new constructor (will override original)
return decoratedConstructor;
};
}
@logClass()
class Base {
prop = 5;
constructor(value: number) {
console.log("Base constructor", value);
this.prop *= value;
}
foo() { console.log("Foo", this.prop); }
static s() { console.log("Static s"); }
}
class Extended extends Base {
constructor(init: number) {
super(init);
console.log("Extended constructor", init);
}
bar() { console.log("Bar", this.prop); }
}
const b = new Base(2);
console.log("Base", b instanceof Base);
b.foo();
Base.s();
const e = new Extended(5);
console.log("Extended", e instanceof Base, e instanceof Extended);
e.bar();
[EDIT] 정적 멤버를 복사하는 줄도 추가되었으며, 그렇지 않으면 장식된 클래스가 정적 메서드를 호출할 때 오류를 발생시킵니다.
데코레이터가 있는 생성자() 뒤와 앞의 런 코드를 좋아하는 경우:
function ClassWrapper() {
return function(target: any) {
// save a reference to the original constructor
var original = target;
// the new constructor behaviour
var f: any = function (...args) {
console.log('ClassWrapper: before class constructor', original.name);
let instance = original.apply(this, args)
console.log('ClassWrapper: after class constructor', original.name);
return instance;
}
// copy prototype so intanceof operator still works
f.prototype = original.prototype;
// return new constructor (will override original)
return f;
};
}
@ClassWrapper()
export class ClassExample {
public constructor() {
console.info('Running ClassExample constructor...');
}
}
let example = new ClassExample();
/*
CONSOLE OUTPUT:
ClassWrapper: before class constructor ClassExample
Running ClassExample constructor...
ClassWrapper: after class constructor ClassExample
*/
언급URL : https://stackoverflow.com/questions/34411546/how-to-properly-wrap-constructors-with-decorators-in-typescript
'programing' 카테고리의 다른 글
Oracle이 여기에 숨겨진 열을 추가하는 이유는 무엇입니까? (0) | 2023.07.06 |
---|---|
WEB-INF 폴더가 Spring Boot 응용 프로그램에 생성되지 않습니까? (0) | 2023.07.06 |
MongoDB: 배열 요소의 속성에 대한 고유 인덱스 (0) | 2023.07.06 |
Mac용 Excel의 배열 수식 (0) | 2023.07.06 |
서버에서 모든 데이터베이스 삭제 (0) | 2023.07.06 |