[SOLVED] Extend record type with a toList function

Issue

This Content is from Stack Overflow. Question asked by devil_inside

I want a “toList” function on the generic record type. Is there a way to achieve something like this?

//this is possible
type MyRecord<K extends string, T> = Record<K, T> & {
    toList(this: MyRecord<K, T>): T[];
} 

//this not. Typescript complains here about using MyRecord as value when it is a type
MyRecord.prototype.toList = function():T[] {
    const list: T[] = [];
    ...
    return list;
};

Where I can use it later like this without having to define a toList function on every assignment.

//this won't work, toList is missing;
const myDictionary: MyRecord<string, string> = { "a": "b", "c": "d" } 
const myDictionaryValues = myDictionary.toList();
myDictionaryValues.forEach(v => console.log(v));
//prints:
//b
//d

Neither the MyRecord.prototype is working nor the declaration in the first line of my use case example (because of the missing “toList”).

I know that it is possible to just have a global function somewhere, which is doing the “toList” thing. That is not what I am asking here.



Solution

There’s currently no way to define a TypeScript object type with both an index signature and properties that don’t match that signature. Typescript index signature and methods

So, you can’t extend a record type with additional functions, unless it’s a record of functions (or you forego type safety altogether and use any).

You could perhaps compose the underlying record as a property, like so:

class MyRecord<K extends string, T> {
    data: Record<K, T> = {} as Record<K, T>;

    toList(): T[] {
        return Object.values(this.data);
    }
}


This Question was asked in StackOverflow by devil_inside and Answered by Toggle It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.

people found this article helpful. What about you?