Intermediate Typescript Questions - Typed Functions
In this post, we will code out a type-safe function.
Hello, this is the second (intermediate level) of my Typescript interview series. I also wrote a post of beginner level questions here. There is also a post of advanced level questions here.
Question Context
Given the following object:
const house = {
isForSale: true,
neighborhood: 'Red Maple',
squareFootage: 123
}
We want to change the following function getValue()
:
function getValue(s) {
return house[s]
}
Such that the following requirements are satisfied:
const onSale = getValue('isForSale') // onSale should be of type boolean
const neighborhood = getValue('neighborhood') // neighborhood should be of type string
const sqft = getValue('area') // should throw type error
const bedRoomsOnFloor = getValue(1) // should throw type error
⚠️ For all of the following questions, let’s assume we are working on the
getValue()
function. If a question asks you how to modify the input or output type, it’s asking in regards to thegetValue()
function above.
Q1 How can specify the input type to be a string?
Warm up question!
Meet the following requirements:
const onSale = getValue('isForSale') // valid
const bedRoomsOnFloor = getValue(1) // should throw error
Q2 How can we specify the input type to be a string that is one of the existing keys in House
?
Such that the following is met:
const onSale = getValue('isForSale') // valid
const neighborhood = getValue('neighborhood') // valid
const sqft = getValue('squareFootage') // valid
const sqft2 = getValue('area') // should throw type error
Answer
Use the typeof and keyof operators.
type House = typeof house
function getValue(s: keyof House) { return house[s]
}
typeof
takes a variable and returns the type definition
keyof
takes a type and returns the keys of the type
Q3 How can we explicitly specify the output type to one of the values inside House
?
Such that the output type of getValue()
is restricted to boolean
, string
, and number
.
Answer
Use the `keyof` operator.function getValue(s: keyof House): House[keyof House] { return house[s]
}
This can be automatically taken care of by Type Inference, making it redundant in practice.
Q4 How can we specify the output type to be the type of the value for a given key?
So far here is our code:
const house = {
isForSale: true,
neighborhood: 'Red Maple',
squareFootage: 123
}
type House = typeof house
function getValue(s: keyof House): House[keyof House] {
return house[s]
}
If we want to retrieve the value for isForSale
, then the typing is one of string
, number
, or boolean
.
const onSale = getValue('isForSale') // string | number | boolean
But we know that the typing of house['isForSale']
is always going to be a boolean.
const house = {
isForSale: true, // always a boolean neighborhood: 'Red Maple',
squareFootage: 123
}
How can we make sure the typings are paired to their proper key-value pairs, such that the following is met?
const onSale = getValue('isForSale') // boolean
const neighborhood = getValue('neighborhood') // string
Answer
Use generics.
function getValue<K extends keyof House>(s: K): House[K] { return house[s]
}
const onSale = getValue('isForSale') // boolean
const neighborhood = getValue('neighborhood') // string
If you are unfamiliar with generics, checkout my ezpz guide about generics
Great! Now we have a getValue()
function that is type safe.
Looking for more? Checkout my this post for more intermediate questions.
Until next time.