You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级TypeORM至0.3.7遇类型错误:如何按moment.Moment类型排序?

问题

将TypeORM从0.2.45版本升级到0.3.7版本后,以下查询代码中的createdAt字段出现类型错误(升级前可正常运行):

const userTotalEvent = await EventRepository.find({
    where: {
        user: { id: user.id },
        type,
        invitationId
    },
    order: {
        createdAt: 'DESC'
    }
});

错误提示:

Type 'string' is not assignable to type 'FindOptionsOrder'.

相关实体及基类定义如下:
Event实体:

@Entity('event')
export default class Event extends BaseEntity {
  @PrimaryGeneratedColumn()
  public id!: number;

  @ManyToOne(() => User, (user: User) => user.event)
  public user!: User;

  @Column({ type: 'int' })
  public verificationAttempts!: number;
}

BaseEntity基类:

export default class BaseEntity {
  @Column({ type: 'datetime', transformer: datetimeSerializer() })
  @Transform(momentToString())
  public readonly createdAt: moment.Moment;

  @Column({ type: 'datetime', transformer: datetimeSerializer() })
  @Transform(momentToString())
  public updatedAt: moment.Moment;

  constructor() {
    super();
    this.createdAt = moment();
    this.updatedAt = moment();
  }
}

解决方案

方法1:显式指定排序值类型

给createdAt的排序值指定FindOptionsOrderValue类型,绕过TypeScript的类型校验:

import { FindOptionsOrderValue } from "typeorm";

const userTotalEvent = await EventRepository.find({
    where: {
        user: { id: user.id },
        type,
        invitationId
    },
    order: {
        createdAt: 'DESC' as FindOptionsOrderValue
    }
});

方法2:用类型定义约束查询选项

将查询选项变量声明为FindManyOptions<Event>类型,让TypeORM正确推断排序字段的合法值:

import { FindManyOptions } from "typeorm";

const options: FindManyOptions<Event> = {
    where: {
        user: { id: user.id },
        type,
        invitationId
    },
    order: {
        createdAt: 'DESC'
    }
};
const userTotalEvent = await EventRepository.find(options);

方法3:兼容日期字段的类型声明

修改BaseEntity中日期字段的类型,添加string类型兼容,让排序字符串能被类型系统识别:

export default class BaseEntity {
  @Column({ type: 'datetime', transformer: datetimeSerializer() })
  @Transform(momentToString())
  public readonly createdAt: moment.Moment | string;

  @Column({ type: 'datetime', transformer: datetimeSerializer() })
  @Transform(momentToString())
  public updatedAt: moment.Moment | string;

  constructor() {
    super();
    this.createdAt = moment();
    this.updatedAt = moment();
  }
}

方法4:改用QueryBuilder构建查询

使用TypeORM的QueryBuilder替代find方法,类型推断更精准,同时也能灵活控制查询逻辑:

const userTotalEvent = await EventRepository.createQueryBuilder('event')
    .where('event.userId = :userId', { userId: user.id })
    .andWhere('event.type = :type', { type })
    .andWhere('event.invitationId = :invitationId', { invitationId })
    .orderBy('event.createdAt', 'DESC')
    .getMany();

内容的提问来源于stack exchange,提问作者Tin Yu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 01:36:01