Node.js/TypeScript中Repository模式问题:ID由数据库自动生成
解决方案
解决这个问题的核心思路是区分「待创建的输入数据」和「已持久化的领域实体」——你的Book类型代表的是已经存入数据库、拥有合法ID的实体,而创建时传入的数据不需要包含ID,具体可以通过以下两种方式处理:
1. 用TypeScript Omit工具类型简化定义
直接在仓库接口中使用Omit<Book, 'id'>作为create方法的参数类型,既复用Book的字段定义,又自动排除id:
export interface BookRepository { // 输入无需id,返回带完整id的Book实体 create(book: Omit<Book, 'id'>): Promise<Book | null> }
在Postgres的实现里,只需将传入的name和author插入数据库,再把返回的自增ID与这两个字段组合成Book对象返回:
export class PostgresBookRepository implements BookRepository { async create(book: Omit<Book, 'id'>): Promise<Book | null> { const result = await pool.query( 'INSERT INTO books (name, author) VALUES ($1, $2) RETURNING id, name, author', [book.name, book.author] ) return result.rows[0] || null } }
2. 显式定义创建输入类型(可读性更强)
如果追求代码的直观性,可以单独定义一个用于创建的输入类型,同样基于Book排除id:
// 专属创建的输入类型,不含id字段 export type CreateBookInput = Omit<Book, 'id'> export interface BookRepository { create(book: CreateBookInput): Promise<Book | null> }
这种方式在团队协作中更清晰,其他开发者能一眼明确创建操作需要的参数。
注意:不要把
Book中的id改成可选属性(id?: number),这会破坏领域实体ID必填的正确性;也不建议用类型断言强行转换无id的对象为Book,会引入类型不安全的风险。
内容的提问来源于stack exchange,提问作者Gigabit
相关产品推荐
相关产品推荐

