Last active
May 28, 2020 07:00
-
-
Save dmorosinotto/706a453c69e8797373d89a960124d8d6 to your computer and use it in GitHub Desktop.
Unionize<T> / Objectify<T> - TypeScript utility helpers to map from Object --> KeyValue Par {k: K , v: V} --> Object
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
// Utility types to map from Object --(Unionize)--> KeyValue Pair {k: K, v: V} --(Objectify)--> back to Object | |
// helpful in case where you need to "tasform/filter/extract" some prop in the Object using Conditional Types | |
// ORIGINAL CODE + READ MORE INFO/SAMPLE USE CASES: https://effectivetypescript.com/2020/05/12/unionize-objectify/ | |
type Unionize<T extends object> = { | |
[k in keyof T]: {k: k; v: T[k]} | |
}[keyof T]; | |
// type PropertyKey = keyof any = string | number | symbol | |
type KVPair = {k: PropertyKey; v: unknown} | |
type Objectify<T extends KVPair> = { | |
[k in T['k']]: Extract<T, {k: k}>['v'] | |
}; |
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
// HELPFULL USE CASES - ORIGINAL CODE + READ MORE INFO: https://effectivetypescript.com/2020/05/12/unionize-objectify/ | |
type OmitKV<T extends KVPair, V> = T extends {v: V} ? never : T; | |
type OmitProperties<T extends object, V> = Objectify<OmitKV<Unionize<T>, V>>; | |
type PickKV<T extends KVPair, V> = T extends {v: V} ? T : never; | |
type PickProperties<T extends object, V> = Objectify<PickKV<Unionize<T>, V>>; | |
type PickKeys<T extends object, V> = Extract<Unionize<T>, {v: V}>['k']; | |
type OmitKeys<T extends object, V> = Exclude<Unionize<T>, {v: V}>['k']; | |
// More correct type defintion for lodash _.invert | |
type SwapKV<T> = | |
T extends {k: infer K, v: infer V} | |
? V extends PropertyKey // <-- additional PropertyKey constraint | |
? {k: V; v: K; } // <-- note the swap! | |
: never | |
: never; | |
type Inverted<T extends object> = Objectify<SwapKV<Unionize<T>>>; |
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
// SAMPLES - ORIGINAL CODE + READ MORE INFO: https://effectivetypescript.com/2020/05/12/unionize-objectify/ | |
type Person = { | |
name: string, | |
title: string, | |
age: number, | |
dob: Date | null, | |
greet: ()=> string | |
} | |
type PersonData = OmitProperties<Person, Function> // type { name: string, title: string, age: number, dob: Date | null } | |
type PersonMethods = PickProperties<Person, Function> // type { great: ()=> string } | |
type KeysOfPersonString = PickKeys<Person, string> // "name" | "title" | |
function indexByStringField<T extends object>(obj: T[], field: PickKeys<T, string>) { /* ... */ } | |
// THE MOST CORRECT JSON DEFINTION I EVER FOUND | |
type Jsonify<T> = T extends {toJSON(): infer U} | |
? U | |
: T extends Array<infer U> | |
? Array<Jsonify<U>> | |
: T extends object | |
? { | |
[P in OmitKeys<T, Function>]: Jsonify<T[P]>; | |
} | |
: T; | |
type PersonDTO = Jsonify<Person>; // type { name: string, title: string, age: number, dob: string | null } | |
const size = { S: "small", L: "large" } as const; | |
type Dsize = Inverted<typeof size>; // type { small: "S", large: "L" } | |
-> { small: "S", large: "L" } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment