LeetCode 2690 - Infinite Method Object
This problem asks us to implement a function that returns an infinite-method object. The defining property of this object is that any method name can be accessed and called, and when invoked, it should return the exact name of the method.
Difficulty: 🟢 Easy
Topics: —
Solution
Problem Understanding
This problem asks us to implement a function that returns an infinite-method object. The defining property of this object is that any method name can be accessed and called, and when invoked, it should return the exact name of the method.
For example, if we create an object like this:
const obj = createInfiniteObject();
Then calling:
obj.hello()
should return:
"hello"
Similarly:
obj.randomMethod123()
should return:
"randomMethod123"
The important detail is that the method names are not predefined. We cannot hardcode a list of allowed methods because the object must support an effectively infinite number of method names. Every property access should dynamically behave like a callable function that returns the property name.
The input shown in the examples, method, is conceptual rather than an actual parameter passed to the function. It represents the method name that will later be called on the returned object. The expected output is simply the exact string of that method name.
The constraint:
0 <= method.length <= 1000
tells us that method names can be empty or quite long, but this does not meaningfully affect performance because we are only returning strings directly. There is no large dataset to process, no iteration over many values, and no heavy computation.
An important implementation detail is that the method names may contain unusual characters such as:
".-qw73n|^2It"
This means we must support both dot notation and bracket notation. Since JavaScript objects allow dynamic property access, we need a mechanism that intercepts arbitrary property access cleanly.
There are a few edge cases worth recognizing upfront. Method names may contain special characters that cannot be accessed through normal dot notation, so bracket access must still work correctly. Method names may also be very long, which should not affect correctness. Another subtle case is that the object must not throw errors for unknown methods, because every possible method name is valid.
Approaches
Brute Force Approach
A brute-force idea would be to predefine a large number of possible method names inside an object.
For example, we might manually store:
{
hello: () => "hello",
world: () => "world"
}
This approach works for known method names because each method explicitly returns its own name. However, it immediately fails the problem requirement because there are infinitely many possible method names. We cannot predict or enumerate every possible property the user might call.
Even if we attempted to generate many names dynamically, we would still never guarantee complete coverage. Therefore, this approach is fundamentally infeasible.
Optimal Approach
The key observation is that we do not actually need to store methods at all. Instead, we only need a way to intercept property access dynamically.
JavaScript provides exactly this capability through a Proxy object. A proxy allows us to define custom behavior whenever a property is accessed.
When someone accesses:
obj.someMethod
the proxy can intercept "someMethod" and return a function:
() => "someMethod"
This means every property access automatically creates the appropriate method on demand. Since property access is handled dynamically, the object effectively supports infinitely many methods without storing them explicitly.
| Approach | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Brute Force | O(N) | O(N) | Requires storing predefined method names, impossible for infinite cases |
| Optimal | O(1) | O(1) | Uses a Proxy to dynamically generate methods |
Algorithm Walkthrough
- Create a new JavaScript
Proxyobject. - Use an empty object
{}as the target because we do not actually need to store any properties. - Define a
gethandler inside the proxy. This handler runs whenever any property is accessed. - When a property name is requested, capture it as
prop. - Return a function that, when called, returns the property name as a string.
- Since every property access goes through the same handler, the object automatically supports infinitely many method names.
Why it works
The crucial property of the solution is that every property access is intercepted by the proxy's get method. Instead of looking for an existing method, the proxy dynamically constructs one that returns the property name. Therefore, for any method name x, calling obj[x]() always returns x, which satisfies the problem definition exactly.
Python Solution
LeetCode provides a JavaScript environment for this problem, but below is a conceptual Python equivalent that demonstrates the same idea using __getattr__.
class InfiniteObject:
def __getattr__(self, method_name: str):
return lambda: method_name
The Python implementation uses __getattr__, which is invoked whenever an attribute does not exist. Instead of raising an error, we dynamically return a lambda function that returns the attribute name.
For example:
obj = InfiniteObject()
print(obj.abc123()) # "abc123"
When abc123 is accessed, __getattr__ receives "abc123" and returns a function that produces that exact string.
Go Solution
Go does not support dynamic method interception like JavaScript proxies or Python magic methods. Therefore, there is no direct equivalent implementation.
For completeness, here is the actual LeetCode JavaScript solution that should be submitted:
// Go does not support infinite dynamic methods.
// LeetCode expects a JavaScript solution for this problem.
The main language-specific difference is that JavaScript supports runtime property interception through Proxy, while Go is statically typed and requires method names to be known at compile time.
Worked Examples
Example 1
Input:
method = "abc123"
Execution:
const obj = createInfiniteObject();
obj["abc123"]();
| Step | Action | Result |
|---|---|---|
| 1 | Create proxy object | Empty proxy created |
| 2 | Access property "abc123" |
get handler runs |
| 3 | Return function () => "abc123" |
Function created |
| 4 | Invoke function | "abc123" |
Output:
"abc123"
Example 2
Input:
method = ".-qw73n|^2It"
Execution:
const obj = createInfiniteObject();
obj[".-qw73n|^2It"]();
| Step | Action | Result |
|---|---|---|
| 1 | Create proxy object | Empty proxy created |
| 2 | Access special-character property | get handler runs |
| 3 | Return function | Function returns exact string |
| 4 | Invoke function | `".-qw73n |
Output:
".-qw73n|^2It"
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(1) | Property lookup and function creation take constant time |
| Space | O(1) | No additional data structures are stored |
The solution is constant time because property access simply triggers the proxy handler and creates a tiny function dynamically. No loops or large memory allocations occur. Space usage is also constant because the object does not maintain a growing collection of methods.
Test Cases
class InfiniteObject:
def __getattr__(self, method_name):
return lambda: method_name
obj = InfiniteObject()
assert obj.abc123() == "abc123" # Example 1
assert obj.__getattr__(".-qw73n|^2It")() == ".-qw73n|^2It" # Example 2
assert obj.test() == "test" # Basic method name
assert obj.x() == "x" # Single character
assert obj.longmethodname123456789() == "longmethodname123456789" # Long name
assert obj.hello_world() == "hello_world" # Underscore name
assert obj.a1b2c3() == "a1b2c3" # Mixed alphanumeric
| Test | Why |
|---|---|
"abc123" |
Validates the first example |
| `".-qw73n | ^2It"` |
"test" |
Confirms ordinary method names |
"x" |
Tests a very short name |
| Long method name | Ensures long strings work |
"hello_world" |
Confirms underscore handling |
"a1b2c3" |
Tests mixed characters |
Edge Cases
One important edge case is special characters in method names. A method like:
obj[".-qw73n|^2It"]()
cannot be accessed with dot notation because it contains invalid identifier characters. A naive implementation that only supports standard method names would fail here. The proxy approach handles this correctly because property names are intercepted dynamically regardless of formatting.
Another important edge case is very long method names, up to length 1000. A poor implementation might try to process or transform the string unnecessarily. Our solution simply returns the property name directly, so long strings work naturally with no performance issues.
A third edge case is unknown method names. In normal objects, calling an undefined method would raise an error. However, this problem requires every possible method name to be valid. The proxy guarantees that no property is ever truly missing, because every access dynamically generates a matching function.