import "stream-chat";
import type { DefaultChannelData } from "stream-chat-react";
declare module "stream-chat" {
interface CustomChannelData extends DefaultChannelData {}
interface CustomMessageData {
custom_property?: string;
}
interface CustomUserData {
profile_picture?: string;
}
interface CustomCommandData {
"custom-command": unknown;
"other-custom-command": unknown;
}
}TypeScript & Custom Data Types
As of version 5.0.0, stream-chat-react has been converted to TypeScript. The stream-chat library was converted to TypeScript in version 2.0.0. These upgrades not only improve the type safety, but also allow integrator-defined typings to be taken into consideration when working with Stream entities such as message or channel through the use of module augmentation (declaration merging), which is a direct replacement for the previous type augmentation mechanism (generics) since stream-chat version 9.0.0 and stream-chat-react version 13.0.0.
There are twelve extendable interfaces in stream-chat, which merge with the base types of Stream entities:
CustomAttachmentDataCustomChannelDataCustomCommandDataCustomEventDataCustomMemberDataCustomMessageDataCustomPollOptionDataCustomPollDataCustomReactionDataCustomUserDataCustomThreadDataCustomMessageComposerData
Best Practices
- Use module augmentation to keep custom data types centralized.
- Extend
DefaultChannelDataif you rely on default UI components. - Keep custom types minimal to avoid bloated payloads.
- Regenerate or re-check types after SDK upgrades.
- Use
unknownfor command payloads when only keys matter.
Note that CustomChannelData is extended within stream-chat-react with commonly used fields (subtitle, image, name) in DefaultChannelData. Extending your declarations with these defaults (see below) isn’t required, but some default components expect specific types. If you change those types, you may need to replace the affected defaults.
Declare Custom Data Types
To extend these custom interfaces you'll have to create a declaration file within your codebase and make sure it's loaded by the TypeScript. Within this file we'll import stream-chat and specific defaults from stream-chat-react and then define the interface augmentations:
Note that CustomCommandData interface is a special case from which only the keys would be used, the value type is not important and unknown would suffice.
That's it, you can check if your augmentations work with similar code:
import { StreamChat } from "stream-chat";
const client = new StreamChat("any-key");
const response = await client.getMessage("id");
const customProperty = response.message.custom_property; // should be `string | undefined` as per our declaration