Type-safe Dictionary in TypeScript

kkazala

Kinga

Posted on December 20, 2021

Type-safe Dictionary in TypeScript

Although Map object has almost everything I need, I recently found myself in need of map() function on a Mapobject... No such luck. ;)
So I implemented it.

export interface IDictionary<T> {
    set(key: string, value: T);
    get(key: string): T;
    delete(key: string): boolean;
    hasKey(key: string): boolean;
    hasValue(value: T): boolean;
    getKeys(): string[];
    getValues(): T[];
    map(fn: (key: string, value: T) => any ): {};

    size: number;
}
export class Dictionary<T> implements IDictionary<T>{ 
    private items: { [key: string]: T } = {};

    public set(key: string, value: T) {
        this.items[key] = value;
    }
    public get(key: string): T {
        return this.items[key];
    }
    public delete(key: string):boolean { 
        if (this.items.hasOwnProperty(key)) { 
            delete this.items[key];
            return true;
        }
        else { 
            return false;
        }
    }

    public hasKey(key: string): boolean {
        return this.items.hasOwnProperty(key);
    }
    public hasValue(value:T): boolean { 
        return Object.values(this.items).includes(value);
    }

    public getKeys(): string[] {
        return Object.keys(this.items);
    }
    public getValues(): T[] {
        return Object.values(this.items);
    }

    public map(mapFn: { (key: string, value:T): any; }): {} { 
        return Object.keys(this.items).map((key) => { 
            return mapFn(key,this.items[key]);
        });

    }
    public format(mapFn: { (key: string, value:T): any; }): any[] { 
        return Object.keys(this.items).map((key) => { 
            return mapFn(key,this.items[key]);
        });
    }

    public get size(): number { 
        return Object.keys(this.items).length;
    }
}
Enter fullscreen mode Exit fullscreen mode

Now, printing Dictionary in a React function couldn't be easier

export default function CommitForm(props: ICommitFormProps) {
    let myDictionary: Dictionary<Array<string>> = (new Dictionary());
...
    return (
        <ul>
            {
                myDictionary.map((key: string, value: string[]) => {
                    return (<li>{value.join(", ")} (type {key}) </li>);
                })
            }
        </ul>
    );
...
}
Enter fullscreen mode Exit fullscreen mode

And in case you want to use the Dictionary in your localized string:

myStrings.d.ts
  Warning_HTML: string;
Enter fullscreen mode Exit fullscreen mode
en-us.js
  "Warning_HTML":"The following values are not supported:<ul>{0}</ul>"
Enter fullscreen mode Exit fullscreen mode
MyReactComponent.tsx
export default function CommitForm(props: ICommitFormProps) {
    let myDictionary: Dictionary<Array<string>> = (new Dictionary());
...

    function getHTML(fields: Dictionary<string[]>): string { 
        return (fields.format((key, value) => { return "<li>" + value.join(", ") + " (type " + key + ") </li>"; })).join();
    }

    return (
    <MessageBar messageBarType={MessageBarType.warning} isMultiline={true} >
    {
        <div dangerouslySetInnerHTML={{ __html: format(strings.Warning_HTML, getHTML(myDictionary)) }} ></div>
    }
    </MessageBar>
    );
...
}
Enter fullscreen mode Exit fullscreen mode

The difference between Object, Mapand Record is widely documented (see e.g. Building a type-safe dictionary in TypeScript for an explanation).

๐Ÿ’– ๐Ÿ’ช ๐Ÿ™… ๐Ÿšฉ
kkazala
Kinga

Posted on December 20, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

ยฉ TheLazy.dev

About