- Published on
TypeScript: How to get type from an Array
Table of Contents
When working with TypeScript, you may come across a situation where you had an array list of possible values and wanted to convert them to a specific type
. That would be useful to enforce a typed check in a function for example like getUsersbySubscription
below.
So it might seem reasonable to manually create a union by re-using those values like type SubscriptionType
.
Problem: Manual type creation to mirror arrays' values
//long list maybe retrived from a DB
const SUBSCRIPTION_TYPE_LIST = ['PREMIUM', 'CLASSIC', 'PLATINUM']
//we need to re-write the lists containt twice manually here in order to create a type
type SubscriptionType = 'PREMIUM' | 'CLASSIC' | 'PLATINUM'
const getUsersbySubscription = (sub: SubscriptionType): number => {
let users = 0
switch (sub) {
case 'PLATINUM':
users = 50
break
case 'PREMIUM':
users = 15
break
case 'CLASSIC':
users = 5
break
}
return 0
}
const subscriptionPlan1 = 'CLASSIC'
const subscriptionPlan2 = 'GOLDEN'
//we want to enforce type checking
console.log(getUsersbySubscription(subscriptionPlan1)) // Logs: 5
//console.log(getUsersbySubscription(subscriptionPlan2)) //π« (TS2345): Argument of type '"GOLDEN"' is not assignable to parameter of type 'SubscriptionType'.
const assertion
Solution: Using By using const assertion we ensure array literals become readonly tuples. So when we want to extract type from an array would be like:
without any type assertion we would get
//long list maybe retrived from a DB
const SUBSCRIPTION_TYPE_LIST = ['PREMIUM', 'CLASSIC', 'PLATINUM']
type SubscriptionType = typeof SUBSCRIPTION_TYPE_LIST // β string []
But with const assertion
only we are a step closer by not yet there:
//long list maybe retrived from a DB
const SUBSCRIPTION_TYPE_LIST = ['PREMIUM', 'CLASSIC', 'PLATINUM'] as const
type SubscriptionType = typeof SUBSCRIPTION_TYPE_LIST // β readonly ["PREMIUM", "CLASSIC", "PLATINUM"]
Eventually we need to construct a type
that assembles the union of those values and in order to fix the previous we need the array version of that typeof
, so
//long list maybe retrived from a DB
const SUBSCRIPTION_TYPE_LIST = ['PREMIUM', 'CLASSIC', 'PLATINUM'] as const
type SubscriptionType = typeof SUBSCRIPTION_TYPE_LIST[number] // β
type SubscriptionType = "PREMIUM" | "CLASSIC" | "PLATINUM"
Finally, we can have our initial code re-written as follows:
//long list maybe retrived from a DB
const SUBSCRIPTION_TYPE_LIST = ['PREMIUM', 'CLASSIC', 'PLATINUM'] as const
type SubscriptionType = typeof SUBSCRIPTION_TYPE_LIST[number] // β
type SubscriptionType = "PREMIUM" | "CLASSIC" | "PLATINUM"
const getUsersbySubscription = (sub: SubscriptionType): number => {
let users = 0
switch (sub) {
case 'PLATINUM':
users = 50
break
case 'PREMIUM':
users = 15
break
case 'CLASSIC':
users = 5
break
}
return 0
}
const subscriptionPlan1 = 'CLASSIC'
const subscriptionPlan2 = 'GOLDEN'
//we want to enforce type checking
console.log(getUsersbySubscription(subscriptionPlan1)) // Logs: 5
//console.log(getUsersbySubscription(subscriptionPlan2)) //π« (TS2345): Argument of type '"GOLDEN"' is not assignable to parameter of type 'SubscriptionType'.