Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 740
feihcsim Avatar asked Oct 14 '25 12:10

feihcsim


1 Answers

Here is a lean alternative (in addition to Patrick Robert's good solution):

type KeyFromVal<T, V> = {
  [K in keyof T]: V extends T[K] ? K : never
}[keyof T];

// we assume the type to be an object literal with string values
// , should also work with number or symbol
type Inverse<M extends Record<string, string>> = {
  [K in M[keyof M]]: KeyFromVal<M, K>
};

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

type MappedTypeInverse = Inverse<MappedType> // { value1: "key1"; value2: "key2"; }
like image 187
ford04 Avatar answered Oct 18 '25 09:10

ford04



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!