如何使用 TypeScript 映射数据库架构和模型



我有一个名为student的数据库表。

id | name | createdAt  | deleted
--------------------------------
1  | foo  | 2017-01-13 | false

当我从数据库中检索值时,我将获得映射到正确类型的值。我有一个这个表的接口:

interface Student {
  id: number;
  name: string;
  createdAt: Date;
  deleted: boolean;
}

为了从数据库中获取值,我正在做这样的事情:

await knex('student').where('deleted', false);

我正在考虑如何替换硬编码字符串以引用表/列,因此可以重命名/删除列并在编译时而不是运行时检测问题。我创建了一个对象,如下所示:

const tables = { student: 'student' };
const cols = {
  id: 'id',
  name: 'name',
  createdAt: 'createdAt',
  deleted: 'deleted',
};
await knex(tables.student).where(cols.deleted, false);

它有效。但是这种方法的问题在于,如果有人更改模型接口(Student)而忘记更改cols对象,它仍然会在编译时工作。

如果我这样做const cols: Student它将验证所有列,但 cols 对象上所有列的类型应该是字符串。

有没有办法做到这一点?也许从这条线开始,或者也许以完全不同的方法?

使用新的 2.1.0 功能非常容易修复。

const tables = { student: 'student' };
const cols: { [P in keyof Student]: string } = {
  id: 'id',
  name: 'name',
  createdAt: 'createdAt',
  deleted: 'deleted',
};
await knex(tables.student).where(cols.deleted, false);

如果您更改学生,这将抱怨,但不会更改 cols 对象。

我可以想象一个类似地图的结构,如下所示

interface MetaDataDescription {
    dbName: string;
    type: any;
}
class StudentMetaData {
    static ID: MetaDataDescription = {dbName: 'id', type: number};
    static NAME: MetaDataDescription = {dbName: 'name', type: string};
    //etc...
}

然后,您将在运行时从 StudentMetaData 中给出的数据(字段名称dbName,字段类型type)生成接口Student。(所有其他型号也是如此)

访问此通用接口中的数据就像genericInstance[StudentMetaData.ID.dbName]保持编译时完整性一样。

在查询中,您将编写await knex(tables.student).where(StudentMetaData.DELETED.dbName, false);,同时保留编译时检查。

对整个结构的任何更改都将在元数据类中的单个点中进行,

最新更新