Types
Complete TypeScript type definitions for melony.
Overview
melony is built with TypeScript and provides comprehensive type definitions for all components, hooks, and utilities. This ensures type safety and excellent developer experience.
Core Types
MelonyPart
Base part structure that represents individual pieces of content in a message.
type MelonyPart<TType = string, TExtra = {}> = {
melonyId: string;
type: TType;
role: Role;
} & TExtra;
Properties
melonyId
- Unique identifier for the parttype
- Type of content (text, image, tool_call, etc.)role
- Who sent the message (user, assistant, system)TExtra
- Additional properties specific to the part typeMelonyMessage
Message container that groups related parts together.
type MelonyMessage<TPart = MelonyPart> = {
id: string;
role: Role;
parts: TPart[];
createdAt: Date;
metadata?: Record<string, any>;
};
Properties
id
- Unique identifier for the messagerole
- Who sent the messageparts
- Array of parts in the messagecreatedAt
- When the message was createdmetadata
- Optional additional dataRole
Enumeration of possible message roles.
type Role = "user" | "assistant" | "system";
Hook Types
useMelonyMessages Options
type UseMelonyMessagesOptions<TPart = MelonyPart> = {
filter?: (part: TPart) => boolean;
groupBy?: (message: MelonyMessage<TPart>) => string;
sortBy?: (a: MelonyMessage<TPart>, b: MelonyMessage<TPart>) => number;
limit?: number;
joinTextDeltas?: boolean | JoinTextDeltasOptions;
mapper?: (data: any) => TPart;
validator?: (data: any) => data is TPart;
};
JoinTextDeltasOptions
type JoinTextDeltasOptions = {
deltaType: string;
idField: string;
deltaField: string;
outputType: string;
outputField: string;
};
useMelonyPart Callback
type MelonyPartCallback<TPart = MelonyPart> = (part: TPart) => void;
Provider Types
MelonyProvider Props
type MelonyProviderProps<TPart = MelonyPart> = {
endpoint?: string;
headers?: Record<string, string>;
children: React.ReactNode;
};
MelonyContext
type MelonyContext<TPart = MelonyPart> = {
endpoint: string;
headers?: Record<string, string>;
messages: MelonyMessage<TPart>[];
status: MelonyStatus;
send: (message: string) => Promise<void>;
};
Status Types
MelonyStatus
type MelonyStatus = "idle" | "requested" | "streaming" | "error";
Status Values
"idle"
- No active requests"requested"
- Request sent, waiting for response"streaming"
- Receiving streaming response"error"
- An error occurredCustom Types
You can extend melony's types to create custom part structures:
Basic Custom Part
// Define your custom part type
type CustomPart = MelonyPart<"text" | "image" | "tool_call", {
text?: string;
imageUrl?: string;
toolName?: string;
toolArgs?: Record<string, any>;
}>;
// Use with MelonyProvider
<MelonyProvider<CustomPart> endpoint="/api/chat">
<YourChatComponent />
</MelonyProvider>
Advanced Custom Part
// More complex custom part with additional metadata
type AdvancedPart = MelonyPart<"text" | "code" | "image" | "video", {
// Text content
text?: string;
language?: string; // For code blocks
// Media content
imageUrl?: string;
videoUrl?: string;
// Metadata
timestamp?: number;
isStreaming?: boolean;
isError?: boolean;
errorMessage?: string;
// Custom fields
priority?: "low" | "medium" | "high";
tags?: string[];
}>;
Custom Message with Metadata
// Custom message type with additional metadata
type CustomMessage = MelonyMessage<CustomPart> & {
conversationId: string;
userId: string;
sessionId: string;
priority: "low" | "medium" | "high";
tags: string[];
isRead: boolean;
isArchived: boolean;
};
Utility Types
melony provides several utility types for common use cases:
TextPart
// Predefined type for text parts
type TextPart = MelonyPart<"text", {
text: string;
}>;
ImagePart
// Predefined type for image parts
type ImagePart = MelonyPart<"image", {
imageUrl: string;
alt?: string;
width?: number;
height?: number;
}>;
ToolCallPart
// Predefined type for tool call parts
type ToolCallPart = MelonyPart<"tool_call", {
toolName: string;
toolArgs: Record<string, any>;
toolResult?: any;
}>;
Type Guards
Use type guards to safely check part types at runtime:
// Type guard functions
function isTextPart(part: MelonyPart): part is TextPart {
return part.type === "text" && "text" in part;
}
function isImagePart(part: MelonyPart): part is ImagePart {
return part.type === "image" && "imageUrl" in part;
}
function isToolCallPart(part: MelonyPart): part is ToolCallPart {
return part.type === "tool_call" && "toolName" in part;
}
// Usage in components
function PartRenderer({ part }: { part: MelonyPart }) {
if (isTextPart(part)) {
return <p>{part.text}</p>;
}
if (isImagePart(part)) {
return <img src={part.imageUrl} alt={part.alt} />;
}
if (isToolCallPart(part)) {
return (
<div>
<strong>Tool:</strong> {part.toolName}
<pre>{JSON.stringify(part.toolArgs, null, 2)}</pre>
</div>
);
}
return null;
}
Generic Constraints
When creating custom types, you can use generic constraints to ensure type safety:
// Constraint to ensure part has required fields
type ValidPart = MelonyPart<string, {
[K in string]: any;
}>;
// Constraint for specific part types
type TextOrImagePart = MelonyPart<"text" | "image", {
text?: string;
imageUrl?: string;
}>;
// Constraint for parts with specific role
type UserPart = MelonyPart<string, any> & {
role: "user";
};
// Usage with constraints
function processPart<T extends ValidPart>(part: T): T {
// Process the part
return part;
}
Migration Types
Types to help with migration from other chat libraries:
// Migration from react-chatbot-kit
type ChatbotKitMessage = {
id: string;
message: string;
type: "user" | "bot";
timestamp: Date;
};
// Convert to melony format
function convertChatbotKitMessage(msg: ChatbotKitMessage): MelonyMessage {
return {
id: msg.id,
role: msg.type === "bot" ? "assistant" : "user",
parts: [{
melonyId: `${msg.id}-part-0`,
type: "text",
role: msg.type === "bot" ? "assistant" : "user",
text: msg.message,
}],
createdAt: msg.timestamp,
};
}
// Migration from react-chat-widget
type ChatWidgetMessage = {
id: string;
text: string;
sender: "user" | "bot";
timestamp: number;
};
function convertChatWidgetMessage(msg: ChatWidgetMessage): MelonyMessage {
return {
id: msg.id,
role: msg.sender === "bot" ? "assistant" : "user",
parts: [{
melonyId: `${msg.id}-part-0`,
type: "text",
role: msg.sender === "bot" ? "assistant" : "user",
text: msg.text,
}],
createdAt: new Date(msg.timestamp),
};
}
TypeScript Best Practices
Use strict TypeScript
Enable strict mode in your tsconfig.json to catch type errors at compile time.
Define types early
Define your custom types before implementing components to ensure consistency.
Use type guards
Implement type guards for runtime type checking and better error handling.
Document complex types
Add JSDoc comments to complex types to improve maintainability.