Chapters - Table of contents →
Chapter 2 introduced how to represent complete data types in TypeScript; However, most of those types are dedicated to representing a specific variable or function.
The reality of modern web applications is quite different, requiring building reusable types.
Let's take a look at some famous examples:
The useRef() example
Referring to the React hook documentation, useRef() has two behaviors:
You might be familiar with refs primarily as a way to access the DOM
(useRef(null)).
If you pass a ref object to React with <div ref={myRef} />, React will set its .current property to the corresponding DOM node whenever that node changes.
In short, useRef(null) returns an immutable ref object that gets its value from a child component, while useRef() returns a mutable ref object that you can use to store a value across renders.
ref2is a type of ref passed down to a component's ref attribute, we cannot mutate ref2.current
You witness that TypeScript knows that the return type of useRef() changes depending on the number of arguments.
We will see how to build such a pattern by leveraging Functions overloads.
The useState() example
1const [open, setOpen] = useState(false)
2
3open // `open` inferred type is `boolean`
4
5const [zipCode, setZipCode] = useState(() => '75000')
6
7zipCode // `zipCode` inferred type is `string`
8
You'll notice that useState() return type is different given the argument value - or return type value if it's a callback.
What we learned so far cannot achieve such behavior; We will need to use TypeScript Generics types to build more "dynamic types."
The InferProps<T> example
Finally, let's get back to prop-types's InferProps<T>:
1import React from 'react'
2import PropTypes, { InferProps } from 'prop-types'
3
4// `props`'s types is inferred from `Button.propTypes`
5// by using `InferType<T>`
6function Button(
7 props: InferProps<typeof Button.propTypes>
8) {
9 return (
10 <button>{props.label}</button>
11 )
12}
13
14Button.propTypes = {
15 label: PropTypes.string.isRequired
16}
17
InferProps<T> is what we could call a "type from type," a type defined by transforming an existing one.
We will see that TypeScript offers many features to build advanced reusable types at scale.