javascript - Skapa en klass med getters baserat på egenskaperna hos en annan klass
Säg att jag har en klass A med hundra egenskaper:
class A {
FOO = "foo";
BAR = "bar";
// (...) 98 more properties
}
I TypeScript, hur går man tillväga för att dynamiskt definiera en klass B med en getter för varje egenskap i klass A?
Den motsvarande statiskt definierade klassen B skulle se ut så här:
class B {
get FOO() {
someFunction('FOO');
}
get BAR() {
someFunction('BAR');
}
// (...) 98 more getters
}
Relationen mellan dessa klasser är som följer:
- ett getter-namn i B är lika med egenskapsnamnet i A
- kroppen av getter i B är exakt anropet av funktionen
someFunctionmed ett enda argument som är en sträng med namnet på gettern
Svar #1
Ett alternativ är att definiera getters på språng:
class A {
FOO = "foo";
BAR = "bar";
// (...) 98 more properties
}
function someFunction(p) {
console.log('someFunction', p)
}
class B {
constructor(a) {
for (let p of Object.getOwnPropertyNames(a))
Object.defineProperty(this, p, {
get: () => someFunction(p)
})
}
}
b = new B(new A)
b.FOO
b.BARJag antar att du behöver skicka a till someFunc också, annars hur skulle det veta från vilket objekt det ska hämta egenskapen?
En annan är att använda en Proxy:
class A {
FOO = "foo";
BAR = "bar";
// (...) 98 more properties
}
function someFunction(p) {
console.log('someFunction', p)
}
class B {
constructor() {
return new Proxy({}, {
get(target, p) {
return p in target ? Reflect.get(target, p) : someFunction(p)
}
})
}
}
b = new B()
b.FOO
b.BARI det senare fallet är B och A faktiskt oberoende, så att B bara är ett "hål"-objekt som omdirigerar allt till someFunc.
Svar #2
Detta är @georgs svar, andra förslaget, något ändrat för att faktiskt fungera för mig:
class A {
FOO = "foo";
BAR = "bar";
// (...) 98 more properties
}
function someFunction(p, moreStuff) {
console.log('someFunction', p, moreStuff)
}
class B extends A {
constructor(private something: Something) {
super();
const someth = this.something;
return new Proxy({} as any, {
get(target, p) {
return p in target ? Reflect.get(target, p) : someFunction(p, someth)
}
})
}
}
b = new B()
b.FOO
b.BAR
