TypeScript Class Utility Kit
This challenge focuses on building a small, yet powerful, set of utility functions for working with TypeScript classes. These utilities will help in creating more dynamic and flexible class-based solutions by allowing introspection and modification of class properties and methods at runtime. This is particularly useful in scenarios like framework development, ORMs, or advanced metaprogramming.
Problem Description
You are tasked with creating a TypeScript utility class, ClassUtils, that provides several static methods for interacting with and manipulating classes. These utilities should be robust and handle various class structures.
Your ClassUtils class should implement the following static methods:
-
getOwnProperties(target: Function): string[]:- Returns an array of all own property names (enumerable and non-enumerable, including symbols) of a given class constructor function.
- This should exclude properties inherited from the prototype chain.
-
getOwnMethods(target: Function): string[]:- Returns an array of all own method names (enumerable and non-enumerable, including symbols) of a given class constructor function.
- A "method" here is defined as an own property whose value is a function.
- This should exclude methods inherited from the prototype chain.
-
hasOwnMethod(target: Function, methodName: string | symbol): boolean:- Returns
trueif the given class constructor function has an own property namedmethodNamethat is a function, andfalseotherwise. - This should not consider inherited methods.
- Returns
-
getPropertyDescriptor(target: Function, propertyName: string | symbol): PropertyDescriptor | undefined:- Returns the
PropertyDescriptorfor an own property of a given class constructor function. - If the property does not exist as an own property on the class itself (not its prototype), it should return
undefined.
- Returns the
Examples
Example 1: getOwnProperties
class MyClass {
static staticProp = 1;
instanceProp = 2; // Not an own property of the class constructor
constructor() {}
}
// Expected Output: ["staticProp", "prototype"] (or similar, depending on JS engine internal properties)
console.log(ClassUtils.getOwnProperties(MyClass));
Example 2: getOwnMethods
class Calculator {
static add(a: number, b: number): number {
return a + b;
}
subtract(a: number, b: number): number {
return a - b;
}
#privateMethod() {
return "private";
}
constructor() {}
}
// Expected Output: ["add", "prototype"] (order might vary)
console.log(ClassUtils.getOwnMethods(Calculator));
Example 3: hasOwnMethod
class Greeter {
static greet(name: string): string {
return `Hello, ${name}`;
}
sayGoodbye(): void {
console.log("Goodbye!");
}
constructor() {}
}
// Expected Output: true
console.log(ClassUtils.hasOwnMethod(Greeter, "greet"));
// Expected Output: false (instance method, not on the class itself)
console.log(ClassUtils.hasOwnMethod(Greeter, "sayGoodbye"));
// Expected Output: false (method does not exist)
console.log(ClassUtils.hasOwnMethod(Greeter, "farewell"));
Example 4: getPropertyDescriptor
class Configurable {
static readonly MAX_RETRIES = 3;
static configurableProp: number | undefined;
constructor() {}
}
// Expected Output: { value: 3,writable: false,enumerable: false,configurable: false }
console.log(ClassUtils.getPropertyDescriptor(Configurable, "MAX_RETRIES"));
// Expected Output: { value: undefined,writable: true,enumerable: true,configurable: true }
console.log(ClassUtils.getPropertyDescriptor(Configurable, "configurableProp"));
// Expected Output: undefined
console.log(ClassUtils.getPropertyDescriptor(Configurable, "nonExistentProp"));
Constraints
- The input
targetto allClassUtilsmethods will always be a valid JavaScriptFunctionthat represents a class constructor. - Property names can be strings or symbols.
- Methods are defined as own properties whose value is a function.
- Performance is important, but correctness and adherence to the problem description are paramount. Avoid overly complex or inefficient solutions.
Notes
- Consider using
Object.getOwnPropertyNames(),Object.getOwnPropertySymbols(), andObject.getOwnPropertyDescriptor()to achieve the desired functionality. - Remember that the
prototypeproperty is an own property of the class constructor itself. - The definition of "method" for
getOwnMethodsandhasOwnMethodis specific: an own property whose value is a function. This means you'll need to check the type of the property's value. - Be mindful of how JavaScript handles properties on constructor functions versus their prototypes.