I'm looking to extend the default indexed anonymous types in Typescript and can't seem to find the right syntax to get the type of the value of an indexed object, if this is at all possible?
Here is the problem:
EDIT:
I've reworked the examples for this to better explain the problem.
// How do we pass the value for T as a dictionary through to the iterator?.
interface Object {
where<T = { [key: string]: any}, K = keyof T>(this: T, iterator: (v: any /* this should be valueof T, not any */, key?: K) => boolean | void): T;
// This works, but you have to specify the type when calling it, this is exactly what I'm trying to avoid.
whereAsArray<S, T = { [key: string]: S }, K = keyof T>(this: T, iterator: (v: S /* this should be valueof T, not S*/, key?: K) => boolean | void): S[] /* this should be valueof T[], not S */;
}
// This problem is agnostic of the implementation. Included here only so that the code runs.
(function Setup() {
if (typeof Object.prototype.where != 'function') { Object.defineProperty(Object.prototype, 'where', { value: function (iterator: (v: any, key?: string) => any) { const keys: string[] = Object.keys(this); const result: any = {}; let i: number; for (i = 0; i < keys.length; i++) { const key = keys[i]; if (this.hasOwnProperty(key)) { const res = iterator(this[key], key); if (res === true) { result[key] = (this[key]); } } } return result; }, writable: true, configurable: true, enumerable: false }); }
if (typeof Object.prototype.whereAsArray != 'function') { Object.defineProperty(Object.prototype, 'whereAsArray', { value: function (iterator: (v: any, key?: string) => any) { const keys: string[] = Object.keys(this); const result: any[] = []; let i: number; for (i = 0; i < keys.length; i++) { const key = keys[i]; if (this.hasOwnProperty(key)) { const res = iterator(this[key], key); if (res === true) { result.push(this[key]); } } } return result; }, writable: true, configurable: true, enumerable: false }); }
})();
(function Test() {
// Typescript knows the type of x, it is explicitly typed here as an object keyed on string, storing only numbers; a dictionary of string=>number.
// Typescript enforces this everywhere you use this dictionary, as shown below:
const x: { [key: string]: number } = {};
x["foo"] = 1;
x["bar"] = 2;
// The code can currently be used like this, and works.. But, if you hover the 'i' variable, you will see that the type is any,
// because I can't figure out how to extract the type of the "value of" T in the interface?
const results = x.where((i, _k) => i !== 1);
console.log(results);
// This works. But we have to specify <number> for TS to figure this out. Question is, is it possible to have TS figure this out from the signature?
// Having to type the function calls should not be necessary.
const results2 = x.whereAsArray<number>((i, _k) => i === 1);
console.log(results2);
})();
Playground link: