extending typescript indexed objects to generically access the type of the value of the indexed object dictionary

I’m posting this as a separate answer because you’ve changed the question. The typings for this are actually pretty simple.

type ValueOf<T> = T[keyof T];

interface Object {
    where<T>(this: T, iterator: (v: ValueOf<T>, key: string) => boolean | void): T; // should become Partial<T> if we are not dealing with a dictionary

    whereAsArray<T>(this: T, iterator: (v: ValueOf<T>, key: string) => boolean | void): ValueOf<T>[];
}

We do not need or want a generic for the key because these functions are for all keys, not a specific key.

Note that when defining the iterator callback, the additional arguments should be listed as required. When you call the where method with a callback, you don’t need to include all of the arguments. But if you make them optional in the callback definition, you won’t be able to actually use them in the body of the callback because they might be undefined.

Typescript Playground Link

I’ve already explained many potentially issues with defining these methods on the Object.prototype, but I do want to bring one to your attention. Our where returns the same type T as the original object. That is not inherently a problem, but it doesn’t match your implementation because arrays are returned as objects rather than arrays. Typescript however expects an array to be returned, leading to runtime errors.

const z = [1, 2, 3];
const filtered: number[] = z.where(v => v > 1);
// the type is number[] but it's actually an object
console.log(filtered);
// so calling array methods on it seems fine to TS, but is a runtime error
console.log(filtered.map(n => n - 1));

CLICK HERE to find out more related problems solutions.

Leave a Comment

Your email address will not be published.

Scroll to Top