TypeScript Custom Implementations
Partial
// Partial means turn each property optional.
// To get the properties we can use keyof
// type A = {
// a: number
// b: string
// }
// type C = keyof A // 'a' | 'b'
// Then we can just use Mapped Type to map each type to optional by ?.
type MyPartial<T> = {
[P in keyof T]?: T[P]
}
Required
// Looking at the code example, we can see that the requirment is to remove the ? on each property name.
// To achieve this, we need to use the - , introduced in TypeScript 2.8.
// - allows us to remove modifiers like readonly and ?.
// type MutableRequired<T> = { -readonly [P in keyof T]-?: T[P] }; // Remove readonly and ?
// type ReadonlyPartial<T> = { +readonly [P in keyof T]+?: T[P] }; // Add readonly and ?
// So the answer to this question is simply a Mapped Type with -.
type MyRequired<Type> = {
[P in keyof Type]-?: Type[P]
}
Readonly
// The requirment is to add readonly on each property name.
// To achieve this, we can just use Mapped Type, which allows us to basically map the property to the readonly verison.
type MyReadonly<T> = {
readonly [P in keyof T]: T[P]
}
Record
// Looking at the description, we need to somehow create an object out of the union type.
// This is perfect use case of Mapped Type.
type MyRecord<K, V> = {
[P in K]: V
}
// But only string, symbol and number can be used as object key, so we need to add constraint by extends
type MyRecord<K extends string | number | symbol, V> = {
[P in K]: V
}
// A useful trick is that we can use keyof any to shorten the restraint, since keyof any would return all the possible types of object keys.
type MyRecord<K extends keyof any, V> = {
[P in K]: V
}
Pick
// The requirment is to pick some properties from the object.
// To achieve this, we can use Mapped Type to map the properties we want to pick.
type MyPick<T, K extends keyof T> = {
[P in K]: T[P]
}