typescripttypescript-genericsmapped-types

How can I get the inverse of a TypeScript mapped type?


I am looking to get the "inverse" of a TypeScript mapped type (whose properties are strictly strings, so as to be "inversible"). To illustrate my desired result, I need a generic type

type Inverse<M> = ...

to be able to transform

type MappedType = {
  key1: 'value1'
  key2: 'value2'
};

into

/**
 * {
 *   value1: 'key1';
 *   value2: 'key2';
 * }
 */
type MappedTypeInverse = Inverse<MappedType>

I've tried a couple things already.. but to no avail:

type Inverse<M> = M extends Record<infer O, infer T> ? Record<T, O> : never;

/**
 * type MappedTypeInverse = {
 *   value1: 'key1' | 'key2'
 *   value2: 'key2' | 'key2'
 * }
 */
type MappedTypeInverse = Inverse<MappedType>
type InverseValue<M extends Record<any, any>, V extends M[keyof M]> = V extends M[infer K] ? K : never;

/**
 * type MappedTypeInverseValue = unknown // expecting 'key1'
 */
type MappedTypeInverseValue = InverseValue<MappedType, 'value1'>

Is this even possible? Any help would be appreciated!


Solution

  • type Foo = {
      key1: "val1";
      key2: "val2"
    }
    
    type Inverse<T extends Record<string, string>> = {
      [K in keyof T as T[K]]: K
    }
    
    type Bar = Inverse<Foo>
    // type Bar = { val1: "key1"; val2: "key2"; }