Last active
January 26, 2025 21:11
-
-
Save flut1/15ae3c37adc52cc6a444ca0266d0f096 to your computer and use it in GitHub Desktop.
Common TypeScript utility 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
/** | |
* Extracts all keys of object T that have a value assignable to V | |
*/ | |
type KeysOfType<T, V> = { | |
[K in keyof T]: T[K] extends V ? K : never | |
}[keyof T]; | |
namespace KeysOfTypeExample { | |
type Foo = { | |
prop1: number, | |
prop2: string, | |
}; | |
type NumberKeysOfFoo = KeysOfType<Foo, number>; | |
// NumberKeysOfFoo = "prop1" | |
} | |
/** | |
* Inverse of KeysOfType | |
* | |
* Extracts all keys of object T that have a value NOT assignable to V | |
*/ | |
type KeysNotOfType<T, V> = { | |
[K in keyof T]: T[K] extends V ? never : K | |
}[keyof T]; | |
namespace KeysNotOfTypeExample { | |
type Foo = { | |
prop1: number, | |
prop2: string, | |
}; | |
type NonNumberKeysOfFoo = KeysNotOfType<Foo, number>; | |
// NonNumberKeysOfFoo = "prop2" | |
} | |
/** | |
* All keys of T which refer to optional or possibly undefined properties | |
*/ | |
export type OptionalKeys<T> = { | |
[K in keyof T]-?: undefined extends T[K] ? K : never; | |
}[keyof T]; | |
namespace OptionalKeysExample { | |
type Foo = { | |
prop1?: number, | |
prop2: string, | |
prop3: boolean | undefined, | |
}; | |
type OptionalKeysOfFoo = OptionalKeys<Foo>; | |
// OptionalKeysOfFoo = "prop1" | "prop3" | |
} | |
/** | |
* Include only the properties of T that have a value assignable to T | |
*/ | |
type FilterProperties<T, V> = Pick<T, KeysOfType<T, V>>; | |
namespace FilterPropertiesExample { | |
type Foo = { | |
prop1: number, | |
prop2: string, | |
}; | |
type FilteredFoo = FilterProperties<Foo, number>; | |
// FilteredFoo = {"prop1": number} | |
} | |
/** | |
* Exclude the properties of T that have a value assignable to T | |
*/ | |
type ExcludeProperties<T, V> = Pick<T, KeysNotOfType<T, V>>; | |
namespace FilterPropertiesExample { | |
type Foo = { | |
prop1: number, | |
prop2: string, | |
}; | |
type FilteredFoo = ExcludeProperties<Foo, number>; | |
// FilteredFoo = {"prop2": string} | |
} | |
/** | |
* One or multiple T | |
*/ | |
export type ArrayOrSingle<T> = Array<T> | T; | |
/** | |
* If the given value is a Promise, will give the resolved type | |
* Otherwise gives the type as-is | |
*/ | |
export type Resolved<T> = T extends Promise<infer R> ? R : T; | |
namespace ResolvedExample { | |
async function foo() { | |
return 5; | |
} | |
type AsyncFoo = ReturnType<typeof foo>; | |
// AsyncFoo = Promise<number> | |
type ResolvedFoo = Resolved<ReturnType<typeof foo>>; | |
// ResolvedFoo = number | |
} | |
type TypedObjectKeys = <TInput>(input: TInput) => Array<keyof TInput>; | |
namespace TypedObjectKeysExample { | |
const testInput = { foo: 1, bar: 'two' }; | |
const keys = (Object.keys as TypedObjectKeys)(testInput); | |
// typeof keys === Array<'foo'|'bar'> | |
} | |
/** | |
* Picks only the properties of T which are optional, and makes them required (not undefined). | |
* This can be used to type the "default values" object for any options object | |
*/ | |
export type DefaultsFor<T> = Required<{ [K in OptionalKeys<T>]: Exclude<T[K], undefined> }>; | |
namespace DefaultsForExample { | |
type Options = { | |
option1?: number, | |
option2: string, | |
option3: boolean | undefined, | |
}; | |
// DefaultsFor<Options> === 'options1' | 'option3' | |
const defaultOptions: DefaultsFor<Options> = { | |
option1: 0, | |
option3: false, | |
} | |
function someFunction(options: Options) { | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment