Skip to content

Instantly share code, notes, and snippets.

@RanolP
Last active November 19, 2019 02:01
Show Gist options
  • Save RanolP/c06fa6ea5b7cca8be757a81d0788a838 to your computer and use it in GitHub Desktop.
Save RanolP/c06fa6ea5b7cca8be757a81d0788a838 to your computer and use it in GitHub Desktop.
I'd like to introduce the `Inverse` type in TypeScript.
// For Readibility, I've separated it into type.
type Keyable = string | number | symbol;
// Get value union type.
// for `{ a: true, b: 3 }` it will give you `boolean | number` type.
// Also for array, it will give you commonest type of the array.
type GetValueUnion<T> = T[keyof T];
// This type will inverse keys and values.
// for `{ a: 'str', b: 3 }` it will give you `{ 3: 'b', str: 'a' }` type.
type Inverse<T> =
// Check is `T` only have `Keyable` values.
GetValueUnion<T> extends Keyable
? {
// V is each element of a value set of the `T`.
// Then extract keys which have `V` as a value.
// GetValueUnion gives we union type of keys.
[V in T[keyof T]]: GetValueUnion<
{
[K in keyof T]: T[K] extends V ? K : never;
}
>;
}
: never;
// For the array inversion, It will remove Array.prototype functions so that `Inverse` can work.
type ObjectifyArray<T extends Array<unknown>> = Omit<T, keyof unknown[]>;
// This one has type `{ 3: 'a', str: 'b' }`
type InverseTest = Inverse<{
a: 3;
b: 'str';
}>;
// This one has type `never`.
type NotInversableTest = Inverse<{
notAllowed: true;
}>;
// This one has type `{ a: "0", 2: "1" }`
type ArrayInverseTest = Inverse<ObjectifyArray<['a', 2]>>;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment