Skip to content

Instantly share code, notes, and snippets.

@N0taN3rd
Created June 10, 2021 18:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save N0taN3rd/dd51f0fb45e2f18c7d3ff0d93007fc94 to your computer and use it in GitHub Desktop.
Save N0taN3rd/dd51f0fb45e2f18c7d3ff0d93007fc94 to your computer and use it in GitHub Desktop.
Just some typescript snippets I have come up with that I would like to use elsewhere
/**
* Extracts the type of the items in type T which is an array/set of type U - we want the type U.
* Aka un-boxes the type U in typescripts generic array T = Array<U>.
* If the supplied type is not an array then that type is returned as is
* See the example for more details
*
* @example
* type ArrayItemType = Unboxed<string[]>
* // ArrayItemType = string
*
* interface Holder<T> {
* // T can be
* fn(a: T, b: T): boolean;
* }
*
* interface ArrayHolder<T extends Array<any>> extends Holder<T> {
* fn(a: Unboxed<T>, b: Unboxed<T>): boolean;
* }
*
* const holder: ArrayHolder<string[]> = {
* fn(a: ArrayItemType, b: ArrayItemType): boolean {
* return a.length === b.length;
* }
* }
*
* // since we have stated ArrayHolder<T extends Array<any>> and use "Unboxed<T>" on as the typing for the arguments of fn
* // we can safely do fun things like treating ArrayHolders like simple Holders because out fn type overload
* // is stated to take arguments of string just like if we were Holder<string>.
* // This is also useful for situations where you use a single generic class (class A<T>) and would like
* // to allow "T = Array<U>" but also support using user supplied functions that take elements of T aka of type U
* const holder2: Holder<string> = holder;
*/
export type Unboxed<T> = T extends Array<infer Item>
? Item
: T extends Map<infer KeyType, infer ValueType>
? [KeyType, ValueType]
: T extends Set<infer Item>
? Item
: T;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment