Created
April 7, 2025 18:06
-
-
Save Pacheco95/9c3a15a704c2c95e15fc68dacf511c9f to your computer and use it in GitHub Desktop.
Typescript type safe proxy function and decorators
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function isPromise(value: any): value is Promise<any> { | |
return ( | |
value !== null && | |
typeof value === "object" && | |
typeof value.then === "function" && | |
typeof value.catch === "function" | |
); | |
} | |
async function asyncFunction<T>(index: number, array: Array<T>) { | |
await new Promise((resolve) => setTimeout(resolve, 100)); | |
return array.at(index); | |
} | |
function syncFunction<T>(index: number, array: Array<T>) { | |
return array.at(index); | |
} | |
function proxy<T extends (...args: any[]) => any>(fn: T): T { | |
return function (...args: Parameters<T>) { | |
const returnValue = fn(...args); | |
if (isPromise(returnValue)) { | |
return Promise.resolve(returnValue).then((resolvedValue) => { | |
console.log(`[${fn.name}] Returned value`, resolvedValue); | |
return resolvedValue; | |
}); | |
} | |
console.log(`[${fn.name}] Returned value`, returnValue); | |
return returnValue; | |
} as T; | |
} | |
function proxyDecorator() { | |
return function <T extends (...args: any[]) => any>( | |
target: any, | |
propertyKey: string, | |
descriptor: TypedPropertyDescriptor<T>, | |
) { | |
const originalMethod = descriptor.value!; | |
descriptor.value = function (this: unknown, ...args: Parameters<T>) { | |
const returnValue = originalMethod.apply(this, args); | |
if (isPromise(returnValue)) { | |
return Promise.resolve(returnValue).then((resolvedValue) => { | |
console.log(`[${propertyKey} Returned value`, resolvedValue); | |
return resolvedValue; | |
}); | |
} | |
console.log(`[${propertyKey}] Returned value`, returnValue); | |
return returnValue; | |
} as T; | |
return descriptor; | |
}; | |
} | |
class ProxyDecoratorExample { | |
@proxyDecorator() | |
async asyncMethod<T>(a: number, l: Array<T>) { | |
await new Promise((resolve) => setTimeout(resolve, 100)); | |
return l.at(a); | |
} | |
@proxyDecorator() | |
syncMethod<T>(a: number, l: Array<T>) { | |
return l.at(a); | |
} | |
} | |
(async () => { | |
const loggedAsyncFunction = proxy(asyncFunction); | |
const loggedSyncFunction = proxy(syncFunction); | |
const numbers = [1, 2, 3, 4]; | |
await loggedAsyncFunction(0, numbers); | |
loggedSyncFunction(1, numbers); | |
const example = new ProxyDecoratorExample(); | |
await example.asyncMethod(2, numbers); | |
example.syncMethod(3, numbers); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment