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!
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"; }