My goal is to create a method that acts as a getter, with the option of taking a parameter. This getter should allow access to an object of type T
, and return either the entire object or a specific property of that object.
The issue I am facing is defining the method in two different places - first in an interface and then in the actual implementation.
This is my proposed solution:
// The Getter interface defines multiple overloads
interface StoreGetter {
<T>(): T;
<T, K extends keyof T>(prop: K): T[K];
}
// The Store interface has a generic type 'T' and exposes the type along with its properties
interface Store<T> {
get: StoreGetter;
// Either of these work individually
// get: <T>() => T;
// get: <T, K extends keyof T>(prop: K) => T[K];
}
export function makeStore<T>(initial: T): Store<T> {
let value: T = initial;
// Overloads must be defined via function declaration
// function get<T>(): T;
// function get<T, K extends keyof T>(prop: K): T[K];
function get(prop?: keyof T) {
if (typeof prop !== 'undefined') {
return value[prop];
}
return value;
}
return {
get,
};
}
const store = makeStore({
text: '',
items: [],
num: 1
});
// Error: Argument of type '"text"' is not assignable to parameter of type 'never'.(2345)
store.get('text')
// Error: Object is of type 'unknown'.(2571)
store.get().
It appears that the conflicting definitions are causing issues.
I need help on how to define this method with overloads and have correct type inference for both calls.