Suppose I have:
class A {
f():void{}
g():void{}
}
const a = new A();
type AFunctions = "f" | "g";
I want to iterate AFunctions and produce new functions. Similar to mapped types but with implementation and without manually writing all keys of course.
Pseudo code
const b: A = {
for F in AFunctions add function F() {
return a[f]();
}
}
You can iterate the properties of the class using Object.getOwnPropertyNames
and Object.getPrototypeOf
.
function mapFunctions<T>(type: new (... params: any[])=> T) : { [P in keyof T] : ()=> void } {
let mapped: { [name: string] : ()=> void } = {}
let p = type.prototype;
while(p != Object.prototype) {
for (const prop of Object.getOwnPropertyNames(p)) {
if(prop == 'constructor') continue;
if(typeof p[prop] !== 'function') continue;
mapped[prop] = ()=> {
console.log(prop);
}
}
p = Object.getPrototypeOf(p);
}
return <any>mapped;
}
class A {
f(): void { }
g(): void { }
}
class B extends A{
h(): void { }
i(): void { }
}
let ss = mapFunctions(B); // has functions f,g,h,i
Tying the type of the function to the result of the function on the origin object is more difficult, Conditional types and their associated inference behavior in 2.8 will let you drill down to return type and argument types, but for now you could only use the full function type, such as { [P in keyof T] : ()=> T[P] }
(for a function with no parameters that return a function with the same signature as the original) or { [P in keyof T] : (fn: T[P])=> void }
(for a function that takes a function with the same signature as the original as a parameter)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With