Domain Types and API Contracts
Separate domain models from transport DTOs when their responsibilities differ. A database entity may contain internal fields, while a public API response should expose only approved data. Use explicit conversion functions at boundaries so transformations are visible and testable.
Avoid assuming that a type alias used by both server and client automatically guarantees wire compatibility. Types can drift, and JSON cannot represent every JavaScript value (such as Date objects) in the same way. Document serialized formats and validate incoming data.
Map an internal model to a response
type UserEntity = {
id: string;
email: string;
passwordHash: string;
createdAt: Date;
};
type UserResponse = {
id: string;
email: string;
createdAt: string;
};
function toUserResponse(user: UserEntity): UserResponse {
return {
id: user.id,
email: user.email,
createdAt: user.createdAt.toISOString()
};
}💡 The conversion function prevents the password hash from leaking and serializes the date as a string. Explicit mapping makes the API contract reviewable.
Key Takeaways
- Separate internal entities from public DTOs when fields differ.
- Map and serialize values deliberately.
- Never expose sensitive internal fields just because they exist on a shared type.
Knowledge Check
Why map a database entity to a separate API response type?