- Infer types from objects and arrays with typescript
- Objects
- Using typeof
- Using keyof
- Indexed Access Type
- What about valueof?
- Arrays
- Objects in TypeScript — The Definitive Guide
- The definition
- Optional properties
- Read-only properties
- How to define an object with dynamic keys?
- How to define a generic object type?
- What is the ‘<>‘ type in TypeScript?
- Object vs object
- How to check if an object is empty?
- Final thoughts
Infer types from objects and arrays with typescript
Sometimes when we are using typescript we will need to use the object’s keys or the object’s values as a type, even some cases we need to use the values in an array as a type as well.
What I want with this post is to explain how to do it in a easy way, and by publishing it I will always have a place to return to if I forget (no-kidding) 😂
Objects
Using typeof
When we use objects, we might want to to make an interface or type to describe the types inside the object, this is fine, but for some cases where we also need to create an object based on this interface we might have some code that might look like duplicate, for example:
interface Fruit name: string; price: number; available: boolean; > const fruit: Fruit = name: "Apple", price: 4, available: true >
const fruit = name: "Apple", price: 4, available: true > type Fruit = typeof fruit;
const initialState = name: "Apple", price: 4, available: true > type Fruit = typeof initialState; function FruitComponent() const [fruit, setFruit] = useState(initialState); >
Using keyof
Using the keyof typescript will generate a new type from the keys of the object. Let’s use the following object as an example. Here is the documentation
const fruits = "cod-1": 'Apple', "cod-2": 'Pear', "cod-3": 'Orange' >
Suppose we have a function where we receive the code of the fruit but it must return the name of the fruit.
function getFruitName(code: string) const name = fruits[code]; return name; >
In this case using typescript we would have this error: . type ‘string’ can’t be used to index type < . >since string is not guaranteed to actually match the keys of the object in this case with «code-1» | «code-2» | «code-3» for this reason the code parameter should have a more exact type, we will do it using keyof
type Code = keyof typeof fruits; function getFruitName(code: Code) const name = fruits[code]; return name; >
We were able to do this: type Code = «code-1» | «code-2» | «code-3» , but to be honest it would only work for small cases like this, it’s not scalable.
Indexed Access Type
This is one of my favorite features, in some cases we need the type of a single property on an object/interface/type so this features will help us. Documentation here Suppose we have the following object:
const fruit = name: "Apple", price: 4, available: true >
// Price expects to be number type Price = typeof fruit["price"]
By using the property in square brackets that we want the typescript to get it from, this also works for interface and type, we just have to omit the typeof here is the example for interface, it’s same for objects as a type
interface TFruit name: string, price: number, available: boolean >; // Available expects to be boolean type Available = TFruit["available"];
What about valueof?
An unusual but possible use case is that we need to use the values of an object as a type, buuut valueof doesn’t exist, don’t worry, we have a solution for this and it’s quite simple. The first step is to get the type of the object keys as we did before:
const fruits = "cod-1": 'Apple', "cod-2": 'Pear', "cod-3": 'Orange' >; type Code = keyof typeof fruits;
Now we are going to use this type and combined with the Indexed Access Type we will get the values of the object as a type
type FruitName = typeof fruits[Code];
Arrays
Another use case, we could have an array whose values we will need as a type, a solution would be to duplicate the list:
const fruits = ['apple', 'pear', 'orange']; type Fruits = 'apple' | 'pear' | 'orange';
Buuut, no ,no, no, duplicate the list is not really correct and maintaining it could be tedious, besides I’m sure we want an elegant solutions, right? how about it looks like this:
const fruits = ['apple', 'pera', 'sandia'] as const; type Fruits = typeof fruits[number];
- as const this assigns the values of the array as literal, so, the type of fruits[0] is not string it is apple literally, if you want to go deep of this, pls review this link
- fruits[number] here we are using indexed-types again, when using it in arrays with [number] allows us to get all the values of the array as a union type, it only works with a array literal.
And thats it, hope this help you 😎
Objects in TypeScript — The Definitive Guide
In TypeScript, just like in JavaScript, an object contains a set of keys and values. Objects are used to group and pass data to functions. In TypeScript, we represent those objects, with object types, usually interfaces or types.
Here is an example of an object with its corresponding TypeScript object type definition.
typescriptinterface IArticle < date: number; content: string; > const article: IArticle = < content: 'new content', date: Date.now(), >;
In this article, I will go over, in detail, objects, object types, answer common TypeScript questions, as well as provide real-life TypeScript examples for better understanding.
The definition
In JavaScript, an object is a complex data type. It contains a set of key/value pairs.
The value of each property of an object can be either:
Using the object literal notation, we can declare an object like so:
typescriptconst book = < publicationDate: Date.now(), title: 'Odysee' >;
We can then use the book object in our code, for example, to pass it as a parameter to a function.
JavaScript has 7 primitive types (number, bigint, string, boolean, null, undefined, and symbol).
In TypeScript, objects are represented with object types. An object type can be either anonymous or named (with an interface or a type).
Here is an example of an anonymous object type:
typescriptconst getDate = (book: < date: number, title: string >): number => < return book.date; >;
Here is the same example, but with a named object type, in this case, an interface:
typescriptinterface IBook < date: number, title: string > const getDate = (book: IBook): number => < return book.date; >;
And the same example one last time, but with a type:
typescripttype Book = < date: number, title: string > const getDate = (book: Book): number => < return book.date; >;
As you can see, when you need to re-use an object type multiple times, it is better to create a named object type.
If you don’t know which one to choose between a type vs an interface, I have written a guide on it.
In TypeScript, a developer can specify 3 things about an object type property:
- The type of the property.
- Whether the property is optional.
- Whether the property is read-only.
Optional properties
You can make a property optional by using the question mark ( ? ).
Here is an example of this:
typescriptinterface IBook < date?: number; title: string; >
In this example, the date field is optional.
Read-only properties
You can mark a property as read-only by using the special readonly TypeScript keyword.
Here is an example of this:
typescriptinterface IBook < date: number; readonly title: string; > const book: IBook = < date: Date.now(), title: 'Odysee' >; // This will not work. book.title = 'Tim';
In this example, we cannot reassign the title property, because it is read-only.
If you want to make all the properties of an interface read-only, use the ReadOnly utility type.
How to define an object with dynamic keys?
If you want to define an object with dynamic keys, you will need to use the index signature. It is very useful when you want to create a TypeScript dictionary.
Here is an example of an object using the index signature:
typescriptinterface IMap < Typescript object values type: string; > const map: IMap = < a: '1', b: '2' >;
As you can see, we can add any property that we want inside the map object.
The best Web Development course in 2023! 👉 Learn Web Development
How to define a generic object type?
Generics allow developers to pass a type as an argument to a function or type. By using generics we are making components much more reusable.
Here is an example of a generic in TypeScript:
typescriptinterface IPerson < favoriteSystem: T; >interface IXbox < title: string; > const person: IPerson = < favoriteSystem: < title: 'xbox' > >;
In this example, we have created a generic interface that accepts different favorite systems.
What is the ‘<>‘ type in TypeScript?
In TypeScript, you can specify an empty object by using the empty type ‘ <> ‘ notation. An empty type describes an object that contains no properties.
Here is an example of an empty type:
If you try to access an empty object’s property you will get a TypeScript compiler error.
Object vs object
Since TypeScript is an extension of JavaScript, it also contains the uppercase Object type. It is very important to understand the difference between them because they are two completely different things.
The uppercase Object is a class that stores key/value pairs and contains multiple helpers function like freeze , create , and many more.
The lowercase object is a type that represents key/value pairs in TypeScript.
How to check if an object is empty?
To check if an object is empty you need to use the Object.keys function.
typescriptconst isEmpty = (obj: any): boolean => < return Object.keys(obj).length === 0; >;
In this helper method, we check that the object contains 0 keys.
Final thoughts
As you can see, objects are the foundation of JavaScript programming, just like the control flow statements (for loop, switch, etc. ). So much, that developers use them practically every time they write a new line of code.
Thus it is very important to understand them well, before learning more complex things.
On the other hand, object types are representations of those objects in TypeScript.
If you have any questions about objects or object types, don’t hesitate to ask them in the comments, I always respond.
Thank you for reading this article, please share it with your fellow TypeScript developers.
The best Web Development course in 2023! 👉 Learn Web Development
Hello! I am Tim Mouskhelichvili, a Freelance Developer & Consultant from Montreal, Canada. I specialize in React, Node.js & TypeScript application development. If you need help on a project, please reach out, and let’s work together.