When modifying existing APIs, ensure backward compatibility to prevent runtime failures and minimize migration effort for consumers. Breaking changes in function signatures, return types, or parameter requirements can cause cascading issues throughout a codebase.
When modifying existing APIs, ensure backward compatibility to prevent runtime failures and minimize migration effort for consumers. Breaking changes in function signatures, return types, or parameter requirements can cause cascading issues throughout a codebase.
Follow these practices for API evolution:
// Bad: Breaking change - adding a required parameter
- embed(chunks: string[]): Promise<number[][]>;
+ embed(chunks: string[], embedding_task: EmbeddingTasks): Promise<number[][]>;
// Good: Backward compatible change
+ embed(chunks: string[], embedding_task?: EmbeddingTasks): Promise<number[][]>;
// Bad: Breaking return type change
- function compileChatMessages(...): ChatMessage[] {
+ function compileChatMessages(...): { compiledChatMessages: ChatMessage[]; lastMessageTruncated: boolean } {
// Good: Backward compatible approach
+ interface ChatMessagesResult {
+ messages: ChatMessage[];
+ lastMessageTruncated?: boolean;
+ }
+ function compileChatMessages(...): ChatMessagesResult {
// Bad: Making previously optional parameters required
- required: ["name", "rule"],
+ required: ["name", "rule", "alwaysApply", "description"],
// Good: Keep core parameters required, make new ones optional
+ required: ["name", "rule"],
+ properties: {
+ alwaysApply: { type: "boolean", default: false },
+ description: { type: "string", default: "" },
+ }
Remember that every API change affects all dependent code. Taking the time to design evolution-friendly interfaces upfront prevents costly migrations later.
Enter the URL of a public GitHub repository