https://www.typescriptlang.org/docs/handbook/utility-types.html

  • Partial: useful for update react component state via setter
  • Required: all fields are set to required, useful to reinforce fields
  • Readonly: all fields are set to readonly
  • Record<Keys, Type>: map the properties of a type to another type
  • Pick<Type, Keys>, Omit<Type, Keys>: include/ not include some properties of a type
  • Exclude<UnionType, ExcludedMembers>: exclude all union members assignable to ExcludedMembers. e.g. type T = Exclude<string | number | (() => void), Function>, type T = string } number
  • Extract<Type, Union>, all types assignable to Union, e.g. type T = Extract<string | number | (() => void), Function>, type T = () => void
  • NonNullable: extract null and undefined
  • Parameters: Type needs to satisfy the constraint (...args:any) => any, and Parameters<Type> will be type of args
  • ConstructorParameters
  • ReturnType
  • InstanceType: type of a class’s instance
  • ThisParameterType
    OmitThisParameter
    ThisType

Intrinsic String Manipulation Types

  • Uppercase
  • Lowercase
  • Capitalize
  • Uncapitalize

Interesting examples

1
2
3
4
5
6
7
8
// ThisParameterType
function toHex(this: Number) {
return this.toString(16)
}

function numberToString(n: ThisParameterType<typeof toHex>) {
return toHex.apply(n)
}
1
2
3
4
5
6
// remove this parameter via bind
function toHex(this: Number) {
return this.toString(16)
}

const fiveToHex: OmitThisParameter<typeof toHex> = toHex.bind(5)

Intersection type & ThisType unity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Intersection type, ThisType unity
type ObjectDescriptor<D, M> = {
data?: D
methods?: M & ThisType<D & M> // Type of 'this' in methods is D & M
}

function makeObject<D, M>(desc: ObjectDescriptor<D, M>): D & M {
let data: object = desc.data || {}
let methods: object = desc.methods || {}
return { ...data, ...methods } as D & M
}

let obj = makeObject({
data: { x: 0, y: 0 },
methods: {
moveBy(dx: number, dy: number) {
this.x += dx // Strongly typed this
this.y += dy // Strongly typed this
},
},
})

obj.x = 10
obj.y = 20
obj.moveBy(5, 5)

When type D = { x: number; y: number } and type M = { moveBy: (dx: number, dy: number) => void }, type D & M is { x: number, y: number } & { moveBy(dx: number, dy: number): number }.

The methods object in the argument to makeObject has a contextual type that includes ThisType<D & M> and therefore the type of this in methods within the methods object is { x: number, y: number } & { moveBy(dx: number, dy: number): number }

Notice how the type of the methods property simultaneously is an inference target and a source for the this type in methods.