For critical functions which you feel will change a lot in the future best to avoid primitive types directly in params and use extensible objects.
Making response objects extensible#
Rather than returning primitive types directly, wrap responses in objects:
// Option 1 - not extensible
class DbUser {
name: string;
age: number;
}
function getUser(id: string): DbUser
// Option 2 - extensible
class APIUserResponse {
user: DbUser
}
function getUser(id: string): APIUserResponseThe second option sounds better as you can simply add error state / tasks in the UserResponse object without requiring frontend and backend refactoring.
Making requests extensible#
Rather than accumulating function parameters, use objects for request handling:
// Hard to read, hard to extend
getUser('1', false, none, true);
// Self-documenting, easy to extend
getUser({
id: '1',
includeDisabled: false,
includeTasks: true
})The second approach is significantly more readable and maintainable.
Key takeaway#
For critical functions which you feel will change a lot in the future best to avoid primitive types directly in params and use extensible objects. Primitive types lack extensibility, while context-dependent objects can provide it.