Dan D Kim

Let's share stories

Intermediate Typescript Questions - Utility Types

2021-12-20 Dan D. Kimtypescript

In this post, we will go over some of the useful utility types.


Hello, this is the third of my Typescript interview series. I also wrote a post of beginner questions, another one for intermediate questions, and one for advanced questions.


Q1 How can we omit properties in types?

Given the following object:

const stock = {
  ticker: 'FB',
  name: 'Meta Platforms, Inc. (FB)',
  marketCap: 928524000000
  volume: 40012637
}

We get the following type:

type Stock = typeof stock

/**
 * type Stock = {
 *  ticker: string;
 *  name: string;
 *  marketCap: number;
 *  volume: number;
 * }
 */

How can we create a type that is a copy of the Stock type but omitting the marketCap and volume properties?

Answer

Use the Omit utility type.

type OmittedStock = Omit<Stock, 'marketCap' | 'volume'>

Q2 How can we pick certain properties in types?

Continuing with the Stock type from Q1, how can we create a copy of the Stock type that only includes the properties ticker and marketCap?

Answer

Use the Pick utility type.

type PickedStock = Pick<Stock, 'marketCap' | 'volume'>

Q3 How can we create a copy of the Stock type but specify all types to be readonly?

Answer

Use the Readonly utility type.

type ReadonlyStock = Readonly<Stock>
const stock: ReadonlyStock = { ... }

stock.name = 'Google' // Error: Cannot assign to 'name' because it is a read-only property.

Q4 How can we copy the Stock type but specify all property value types to be of type string ?

Such that the new type looks like as follows:

type StringsOnly = {
 ticker: string;
 name: string;
 marketCap: string;
 volume: string;
}
Answer

Use the Record utility type.

type StringsOnly = Record<keyof Stock, string>

Q5 Last question - object with functions

❗️ This is harder than the previous ones ❗️

Given the following:

const trader = {
  buyStock: (s: string) => canBuy(s) ? true : false,
  sellStock: (s: string) => canSell(s) ? true : false
}

We will get the following type:

type Trader = typeof trader

/**
 * type Trader = {
 *   buyStock: (s: string) => boolean;
 *   sellStock: (s: string) => boolean;
 * }
 */

But how can we create a type that simply extracts the return types of the functions, resulting in the following:

/**
 * type TraderReturnType = {
 *   buyStock: boolean;
 *   sellStock: boolean;
 * }
 */
Hint
type TraderReturnType = {
  /*YOUR CODE HERE*/: /*YOUR CODE HERE*/<Trader[P]>
}

/**
 * type TraderReturnType = {
 *   buyStock: boolean;
 *   sellStock: boolean;
 * }
 */
Answer

Create a union of Trader’s keys via Property in keyof Type, iterate through it, and define the value via the ReturnType utility type.

type TraderReturnType = {  [P in keyof Trader]: ReturnType<Trader[P]>}
/**
 * type TraderReturnType = {
 *   buyStock: boolean;
 *   sellStock: boolean;
 * }
 */

This is a hard one. Not only does it cover ReturnType but also Mapped Types.

P in keyof Trader is explained in Mapped Types.


That’s all, hope you learned something.

Until next time.