DEV Community

Irakλi Safareli
Irakλi Safareli

Posted on

non-string keys in object literal syntax JS


type KeyStore <T> =  {
    asKey: (value: T) => symbol;
    fromKey: (key: symbol) => [] | [T];
}

const mkKeyStore = <T>():KeyStore<T> => {
  const map = new Map<symbol,T>();
  const asKey = (value: T) : symbol =>  {
    const key = Symbol()
    map.set(key, value);
    return key
  }

  const fromKey = (key: symbol): [] | [T] => {
    if (map.has(key)) { 
      return [map.get(key)!]
    }
    return []
  }
  return {asKey, fromKey}
}


const mapMakerMaker = <K>(s:KeyStore<K>) => <T>(record:Record<Extract<K,string | number | symbol> | symbol, T>): Map<K,T> => {
  const stringEntires:[string, T][] = Object.entries<T>(record)
  const entires1 = stringEntires as any as [K,T][]

  const symbols = Object.getOwnPropertySymbols(record);
  const entries2 = symbols.flatMap(key => s.fromKey(key).map((v):[K,T] => [v, record[key]] ))
  const map = new Map<K,T>([
    ...entires1,
    ...entries2
  ])
  return map
}

const keyStore = mkKeyStore<string | ["required",string]>()
const required = (key:string) => keyStore.asKey(["required", key])
const mkMap = mapMakerMaker(keyStore);

const x = mkMap({
 [required("asd")]: "string",
 basd: "int"
})

console.log(x)
// Map (2) {"basd" => "int", ["required", "asd"] => "string"} 
Enter fullscreen mode Exit fullscreen mode

Top comments (0)