Last active
November 19, 2019 02:01
-
-
Save RanolP/c06fa6ea5b7cca8be757a81d0788a838 to your computer and use it in GitHub Desktop.
I'd like to introduce the `Inverse` type in TypeScript.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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