Over the past few years of using Typescript and slowly getting comfortable writing complex custom types, I have amassed a collection of small helper types from around the internet. Here are a few of them that I end up adding to almost all my major projects and how I use them:
Unpromise
Sometimes you need to get the resolved value of a Promise<T> wrapped type, mostly when using along with the inbuilt ReturnType type:
type Unpromise<T> = T extends Promise<infer U> ? U : T;
type a = Promise<number>;
type x = Unpromise<a>; // number
Use with ReturnType to make ReturnTypeResolved:
type ReturnTypeResolved<T extends (...args: any) => any> = Unpromise<
ReturnType<T>
>;
function test(): Promise<{ weird: "value" }> {
return Promise.resolve({ weird: "value" });
}
type WeirdType = ReturnTypeResolved<typeof test>;
PlainObject
I know we have the inbuilt Record but this is such a common and frequent use case that I like having this around:
type PlainObject<T = any> = Record<string, T>;
type NumMap = PlainObject<number>;
const a: NumMap = {
key1: 1,
key2: 2,
keyx: "x", // ERROR: expected number
};
You can also create a reverse of this, ValueOf<T>:
type ValueOf<T> = T[keyof T];
type x = ValueOf<NumMap>; // number
RecursivePartial
Partial but for nested objects, most useful when declaring defaults or merging some overrides for a config type:
type RecursivePartial<T> = {
[P in keyof T]?: T[P] extends (infer U)[]
? RecursivePartial<U>[]
: T[P] extends object
? RecursivePartial<T[P]>
: T[P];
};
const config = {
a: {
x: {
p: 1,
q: 2,
},
y: "nested",
z: "value",
},
b: "root",
c: "value",
};
const configOverride: RecursivePartial<typeof config> = {
a: {
x: {
p: "wrong", // should be number
},
},
};
Also See
Go over the inbuilt utility types in the Typescript Docs. And checkout this great library, utility-types on Github for other common types people tend to use.
Credits
Links to the various places I originally found these from:
Unpromise: Sourced from this StackOverflow Answer: https://stackoverflow.com/a/53196435/9485498RecursivePartial: Sourced from this StackOverflow Answer: https://stackoverflow.com/a/51365037/9485498