Skip to content

Instantly share code, notes, and snippets.

@erodactyl
Last active March 3, 2023 11:47
Show Gist options
  • Save erodactyl/cb445f8e159d50883c81da57d3c6b656 to your computer and use it in GitHub Desktop.
Save erodactyl/cb445f8e159d50883c81da57d3c6b656 to your computer and use it in GitHub Desktop.
Implementing TypeScript utility types (https://www.typescriptlang.org/docs/handbook/utility-types.html) from scratch.
/**
* `Record<Keys, Type>`
*
* Constructs an object type whose property keys are Keys and whose property values are Type. This utility can be used to map the properties of a type to another type.
*
* https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeys-type
*/
type _Record<K extends string | number | symbol, T> = {
[P in K]: T;
};
/**
* `Awaited<Type>`
*
* This type is meant to model operations like await in async functions, or the .then() method on Promises - specifically, the way that they recursively unwrap Promises.
*
* https://www.typescriptlang.org/docs/handbook/utility-types.html#awaitedtype
*/
type _Awaited<T> = T extends {
then: (onfullfilled: (arg: infer R) => any) => any;
}
? _Awaited<R>
: T;
/**
* `Parial<Type>`
*
* Constructs a type with all properties of Type set to optional. This utility will return a type that represents all subsets of a given type.
*
* https://www.typescriptlang.org/docs/handbook/utility-types.html#partialtype
*/
type _Partial<T> = T extends _Record<any, any>
? {
[K in keyof T]?: T[K];
}
: T;
/**
* Required<Type>
*
* Constructs a type consisting of all properties of Type set to required. The opposite of Partial.
*
* https://www.typescriptlang.org/docs/handbook/utility-types.html#requiredtype
*/
type _Required<T> = T extends _Record<any, any>
? {
[K in keyof T]-?: T[K];
}
: T;
/**
* `Readonly<Type>`
*
* Constructs a type with all properties of Type set to readonly, meaning the properties of the constructed type cannot be reassigned.
*
* https://www.typescriptlang.org/docs/handbook/utility-types.html#readonlytype
*/
type _Readonly<T> = T extends _Record<any, any>
? {
readonly [K in keyof T]: T[K];
}
: T;
/**
* `Pick<Type, Keys>`
*
* Constructs a type by picking the set of properties Keys (string literal or union of string literals) from Type.
*
* https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys
*/
type _Pick<T extends _Record<any, any>, K extends keyof T> = {
[P in K]: T[P];
};
/**
* `Omit<Type, Keys>`
*
* Constructs a type by picking all properties from Type and then removing Keys (string literal or union of string literals).
*
* https://www.typescriptlang.org/docs/handbook/utility-types.html#omittype-keys
*/
type _Omit<T extends _Record<any, any>, K extends string | number | symbol> = {
[P in keyof T as P extends K ? never : P]: T[P];
};
/**
* `Exclude<UnionType, ExcludedMembers>`
*
* Constructs a type by excluding from UnionType all union members that are assignable to ExcludedMembers.
*
* https://www.typescriptlang.org/docs/handbook/utility-types.html#excludeuniontype-excludedmembers
*/
type _Excluded<U, E> = U extends E ? never : U;
/**
* `Extract<Type, Union>`
*
* Constructs a type by extracting from Type all union members that are assignable to Union.
*
* https://www.typescriptlang.org/docs/handbook/utility-types.html#extracttype-union
*/
type _Extract<T, U> = T extends U ? T : never;
/**
* `NonNullable<Type>`
*
* Constructs a type by excluding null and undefined from Type.
*
* https://www.typescriptlang.org/docs/handbook/utility-types.html#nonnullabletype
*/
type _NonNullable<T> = T extends undefined ? never : T extends null ? never : T;
/**
* `Parameters<Type>`
*
* Constructs a tuple type from the types used in the parameters of a function type Type.
*
* https://www.typescriptlang.org/docs/handbook/utility-types.html#parameterstype
*/
type _Parameters<Fn extends (...args: any[]) => any> = Fn extends (
...args: infer P
) => any
? P
: never;
/**
* `ReturnType<Type>`
*
* Constructs a type consisting of the return type of function Type.
*
* https://www.typescriptlang.org/docs/handbook/utility-types.html#returntypetype
*/
type _ReturnType<Fn extends (...args: any[]) => any> = Fn extends (
...args: any[]
) => infer R
? R
: never;
/**
* `ConstructorParameters<Type>`
*
* Constructs a tuple or array type from the types of a constructor function type. It produces a tuple type with all the parameter types (or the type never if Type is not a function).
*
* https://www.typescriptlang.org/docs/handbook/utility-types.html#constructorparameterstype
*/
type _ConstructorParameters<T extends abstract new (...args: any[]) => any> =
T extends abstract new (...args: infer P) => any ? P : never;
/**
* `ThisParameterType<Type>`
*
* Extracts the type of the this parameter for a function type, or unknown if the function type has no this parameter.
*
* https://www.typescriptlang.org/docs/handbook/utility-types.html#thisparametertypetype
*/
type _ThisParameterType<T> = T extends (this: infer This, ...args: any[]) => any
? This
: unknown;
/**
* `InstanceType<Type>`
*
* Constructs a type consisting of the instance type of a constructor function in Type.
*
* https://www.typescriptlang.org/docs/handbook/utility-types.html#instancetypetype
*/
type _InstanceType<T extends abstract new (...args: any[]) => any> =
T extends abstract new (...args: any[]) => infer R ? R : never;
/**
* `OmitThisParameter<Type>`
*
* Removes the this parameter from Type. If Type has no explicitly declared this parameter, the result is simply Type. Otherwise, a new function type with no this parameter is created from Type. Generics are erased and only the last overload signature is propagated into the new function type.
*
* https://www.typescriptlang.org/docs/handbook/utility-types.html#omitthisparametertype
*/
type _OmitThisParameter<T> = T extends (
this: any,
...args: infer Args
) => infer Res
? (...args: Args) => Res
: T;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment