How to express a type that represents an associative array whose keys determine the type of the value?


I’m fairly new to type systems and theory, so I would appreciate some guidance in a problem that sparked my interest.

I would like to understand what type system features are required so a compiler can enforce that a given key will return a value of the same type as the one the key was associated with in the first place.

A practical version of my problem is to declare a Map in TypeScript that allows a developer experience like in the pseudocode below:

const cache =  new  Map<K,  V>()  cache.set('Foo',  Error('R'))  cache.set('Bar',  1)  cache.get('Foo')  // Return value typed as Error.    cache.get('Bar')  // Return value typed as number.  cache.get('Qux')  // Compilation error. 

What would the type of K and V be?