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

使用MongoDB的.countDocuments方法时遇到类型错误

使用MongoDB的.countDocuments方法时遇到类型错误

Hey there, let's break down why you're hitting this TypeScript error and how to fix it.

The core issue here is that your generic type T only extends Mongoose's Document interface, but TypeScript can't confirm that every possible T will have a createdAt field. Since your filter relies on createdAt, TypeScript throws an error because it can't guarantee that property exists on all models you might pass to this function.

Fix: Add a Type Constraint to Ensure createdAt Exists

The cleanest way to resolve this is to enforce that any model passed to this function must include a createdAt field. Here's how to do it:

First, define an interface that requires the createdAt property:

interface HasCreatedAt {
  createdAt: Date;
}

Then update your function's generic type to extend both Document and this new interface:

import { Document, Model, FilterQuery } from "mongoose";

interface MonthData {
    month: string;
    count: number;
};

interface HasCreatedAt {
  createdAt: Date;
}

export async function generateLast12MonthsData<T extends Document & HasCreatedAt>(
    model: Model<T>
): Promise<{last12Months:MonthData[]}> {
    const last12Months: MonthData[] = [];
    const currentDate = new Date();
    currentDate.setDate(currentDate.getDate() + 1);

    for(let i=11; i>=0; i--){
        const endDate = new Date(
            currentDate.getFullYear(),
            currentDate.getMonth(),
            currentDate.getDate() - i * 28
        );

        const startDate = new Date(
            endDate.getFullYear(),
            endDate.getMonth(),
            endDate.getDate() - 28
        );

        const monthYear = endDate.toLocaleString(
            'default',
            {
                day: "numeric",
                month: "short",
                year: "numeric",
            }
        );

        const count = await model.countDocuments(
            {
                createdAt: {
                    $gte: startDate,
                    $lt: endDate,
                },
            }
        );

        last12Months.push(
            {
                month: monthYear,
                count,
            }
        )
    }
    return { last12Months };
}

This tells TypeScript that any model passed to generateLast12MonthsData must have a createdAt field of type Date, making your filter valid and eliminating the error.

Alternative (Less Safe) Approach: Type Assertion

If for some reason you can't add the type constraint (though this isn't recommended for type safety), you could use a type assertion to bypass the error:

const count = await model.countDocuments(
    {
        createdAt: {
            $gte: startDate,
            $lt: endDate,
        },
    } as FilterQuery<T>
);

This works but skips TypeScript's checks, so you risk passing a model without createdAt which would cause runtime issues. Stick with the first solution for better safety.

备注:内容来源于stack exchange,提问作者Minh Dương Nguyễn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.17 12:37:59