Last active
December 2, 2021 18:56
-
-
Save ferdaber/7546bb3b4c6e77a7de07edd177bc2c44 to your computer and use it in GitHub Desktop.
Useful Types
This file contains hidden or 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
| type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>> | |
| type Diff<T, U> = Omit<T, Extract<keyof U, keyof T>> | |
| // works because {} will extend a pick of an optional property | |
| // i.e. {} extends { foo?: string } because it's potentially undefined | |
| // abuses the fact that the compiler treats assignability specially for object types | |
| type OptionalKeys<T> = { [K in keyof T]-?: {} extends Pick<T, K> ? K : never }[keyof T] | |
| type RequiredKeys<T> = Exclude<keyof T, OptionalKeys<T>> | |
| // in a weak type, the empty interface extends that type since all of its properties can be undefined | |
| type IsWeak<T> = {} extends T ? true : false | |
| // check by doing `true extends IsNullable<T> ? ...` | |
| type IsNullable<T> = true extends (T extends null | undefined | void ? true : false) ? true : false | |
| // takes advantage of conditional type short circuiting with 'any' where it unions both conditional type branches | |
| type IsAny<T> = boolean extends (T extends never ? true : false) ? true : false | |
| // take advantage of how infer enumerates over keys in the implementation, and will exclude `never`s | |
| // this no longer works as of ??? | |
| type KnownKeys<T> = { | |
| [K in keyof T]: string extends K ? never : number extends K ? never : K | |
| } extends { [K in keyof T]: infer U } ? U : never; | |
| // for ts4.1 this works | |
| type KnownKeys<T> = { | |
| [ P in keyof T as string extends P ? never : number extends P ? never : P ] : T[P] | |
| } | |
| // use to explicitly create a tuple type without widening | |
| function tuple<T extends any[]>(...elements: T): T { return elements } | |
| // turns a union into an intersect by switching the variance position of the assignability check | |
| // since function parameters are checked contravariantly when checking assignability of callable types | |
| type IntersectUnion<T> = (T extends any ? (param: T) => unknown : never) extends (( | |
| params: infer U, | |
| ) => unknown) | |
| ? U | |
| : never; | |
| // infer a type without using it as a constraint, can be used to reverse contravariant type checking for function params | |
| // P is inferred as-is and type-checked, and the full type of `func` is inferred via intersection type which is always | |
| // compatible with its companion call signature | |
| interface CallSignature<P, R = any> { (param: P): R } | |
| function hof<P extends Supertype, F>(func: CallSignature<P> & F): any | |
| // constrain a type such that all of its properties are a certain type, without making it have an index signature | |
| type Map<T, U> = { [K in keyof T]: U } | |
| function mapOfNumbers<E extends Map<E, U>>(map: E): void |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment