# Typing
If you are using TypeScript in your project, you can leverage built-in TypeScript support to ensure type safety and enable autocompletion when working with the channel object.
## Provide a type for the channel object
You can provide a type parameter to the `channel.object.get()` method to specify the expected structure of the channel object:
```javascript
import { LiveCounter, LiveMap } from 'ably/liveobjects';
// Define the expected structure of your channel object
type MyObject = {
visits: LiveCounter;
reactions: LiveMap<{
likes: LiveCounter;
hearts: LiveCounter;
}>;
settings: LiveMap<{
theme: string;
notifications: boolean;
}>;
};
// Get a typed PathObject for the channel
const myObject = await channel.object.get();
```
This enables TypeScript to infer the correct types when accessing and mutating objects. TypeScript surfaces the correct set of methods that are expected for the current `Instance` or `PathObject` and infers the correct arguments and return values for all methods:
```javascript
// TypeScript knows 'visits' is a LiveCounter
const visits = myObject.get('visits');
await visits.increment(5); // Type-safe
// TypeScript knows the structure of 'reactions'
const reactions = myObject.get('reactions');
const likes = reactions.get('likes');
await likes.increment(1); // Type-safe
// TypeScript knows 'theme' is a string
const theme = myObject.get('settings').get('theme');
const themeValue: string | undefined = theme.value();
// Type errors are caught at compile time
await reactions.set('likes', 'invalid');
// Error: Argument of type 'string' is not assignable to parameter of type 'LiveCounter'
```
When obtaining [Instance](https://ably.com/docs/liveobjects/concepts/instance) objects, TypeScript automatically infers the correct instance type:
```javascript
type MyObject = {
visits: LiveCounter;
settings: LiveMap<{
theme: string;
}>;
};
const myObject = await channel.object.get();
const visits = myObject.get('visits').instance();
await visits?.increment(1); // TypeScript knows visits is an Instance of a LiveCounter
const value: number | undefined = visits?.value(); // TypeScript knows the LiveCounter has a number value
const settings = myObject.get('settings').instance();
await settings?.set('theme', 'dark'); // TypeScript knows settings is an Instance of a LiveMap
const theme: string | undefined = settings?.get('theme');
```
TypeScript also infers the correct instance type when using [batch operations](https://ably.com/docs/liveobjects/batch):
```javascript
type MyObject = {
visits: LiveCounter;
settings: LiveMap<{
theme: string;
}>;
};
const myObject = await channel.object.get();
await myObject.batch((ctx) => {
const visits = ctx.get('visits');
visits?.increment(1); // TypeScript knows visits is a LiveCounter
const value: number | undefined = visits?.value(); // TypeScript knows the LiveCounter has a number value
const settings = ctx.get('settings');
settings?.set('theme', 'dark'); // TypeScript knows settings is a LiveMap
const theme: string | undefined = settings?.get('theme');
});
```
## Define reusable types
You can define and export types for reuse across your application:
```javascript
// types/liveobjects.ts
import { LiveCounter, LiveMap } from 'ably/liveobjects';
export type ReactionsType = {
likes: LiveCounter;
hearts: LiveCounter;
fire: LiveCounter;
};
export type UserProfileType = {
name: string;
score: LiveCounter;
settings: LiveMap<{
theme: string;
notifications: boolean;
}>;
};
export type ChannelObjectType = {
reactions: LiveMap;
users: LiveMap<{
[userId: string]: LiveMap;
}>;
};
```
Then import and use these types where needed:
```javascript
import type { ChannelObjectType } from './types/liveobjects';
const myObject = await channel.object.get();
// Fully typed access
const userScore = myObject
.get('users')
.get('user123')
.get('score');
await userScore.increment(10); // Type-safe
```
## Use per-channel types
When your application uses multiple channels with different object structures, you can specify different types for each:
```javascript
// Define types for different channels
type ReactionsChannelObject = {
likes: LiveCounter;
hearts: LiveCounter;
};
type LeaderboardChannelObject = {
players: LiveMap<{
[playerId: string]: LiveMap<{
name: string;
score: LiveCounter;
}>;
}>;
};
// Get typed objects for different channels
const reactionsChannel = client.channels.get('reactions');
const reactions = await reactionsChannel.object.get();
const leaderboardChannel = client.channels.get('leaderboard');
const leaderboard = await leaderboardChannel.object.get();
// Each channel has its own type safety
await reactions.get('likes').increment(1); // Type-safe for reactions
const players = leaderboard.get('players'); // Type-safe for leaderboard
```