# 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.md) 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.md): ### 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 ``` ## Related Topics - [Batch operations](https://ably.com/docs/liveobjects/batch.md): Group multiple objects operations into a single channel message to apply grouped operations atomically and improve performance. - [Lifecycle events](https://ably.com/docs/liveobjects/lifecycle.md): Understand lifecycle events for Objects, LiveMap and LiveCounter to track synchronization events and object deletions. - [Inband objects](https://ably.com/docs/liveobjects/inband-objects.md): Subscribe to LiveObjects updates from Pub/Sub SDKs. - [Object storage](https://ably.com/docs/liveobjects/storage.md): Learn about LiveObjects object storage. - [Using the REST SDK](https://ably.com/docs/liveobjects/rest-sdk-usage.md): Learn how to work with Ably LiveObjects using the REST SDK - [Using the REST API](https://ably.com/docs/liveobjects/rest-api-usage.md): Learn how to work with Ably LiveObjects using the REST API ## Documentation Index To discover additional Ably documentation: 1. Fetch [llms.txt](https://ably.com/llms.txt) for the canonical list of available pages. 2. Identify relevant URLs from that index. 3. Fetch target pages as needed. Avoid using assumed or outdated documentation paths.