Skip to content

Instantly share code, notes, and snippets.

@foretoo
Created August 20, 2023 13:00
Show Gist options
  • Save foretoo/7c9e8f3d7312f1702662e6f82d57d427 to your computer and use it in GitHub Desktop.
Save foretoo/7c9e8f3d7312f1702662e6f82d57d427 to your computer and use it in GitHub Desktop.
Extension of a loosely typed Map<K, V> generic in TypeScript
interface TypedMap<M extends Record<string | number | symbol, any>> extends Map<keyof M, any> {
get: <K extends keyof M>(key: K) => M[K]
set: <K extends keyof M>(key: K, value: M[K]) => this
has: <K extends keyof M>(key: K) => boolean
delete: <K extends keyof M>(key: K) => boolean
forEach: (callbackFn: (value: M[keyof M], key: keyof M, map: TypedMap<M>) => void, thisArg?: any) => void
entries: () => IterableIterator<[ keyof M, M[keyof M] ]>
keys: () => IterableIterator<keyof M>
values: () => IterableIterator<M[keyof M]>
[Symbol.iterator]: () => IterableIterator<[ keyof M, M[keyof M] ]>
}
// how to use:
interface IMap {
foo: string
bar: number
}
const map = new Map() as TypedMap<IMap>
map.set('foo', 'a') // ok
map.set('bar', 'b') // Error: Argument of type 'string' is not assignable...
const foo = map.get('foo') // output type: string
const bar = map.get('bar') // output type: number
const baz = map.get('baz') // Error: Argument of type '"baz"' is not assignable...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment