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

使用Node原生test模块Mock时如何指定重载类型

使用Node.js原生node:test Mock重载函数时的类型匹配问题

我用Node.js原生node:test的mock库来Mock Nest.js的NestFactory.create重载函数,代码如下:

import { LoggerService } from "@nestjs/common";
import { NestFactory } from "@nestjs/core";
import { equal } from "node:assert/strict";
import { suite, test } from "node:test";

suite("Example", async () => {
  test("How to type the override", async ({ mock }) => {
    const create = mock.method(NestFactory, "create", async () => ({}));

    equal(
      create.mock.calls[0].arguments[1].logger instanceof LoggerService,
      true,
    );
  })
})

create存在两个重载定义:

create<T extends INestApplication = INestApplication>(module: IEntryNestModule, options?: NestApplicationOptions): Promise<T>;

create<T extends INestApplication = INestApplication>(module: IEntryNestModule, httpAdapter: AbstractHttpAdapter, options?: NestApplicationOptions): Promise<T>;

实际调用的是第一个重载(传入带logger属性的options对象),但TypeScript默认将create.mock.calls[0].arguments[1]的类型匹配为最后一个重载的AbstractHttpAdapter,导致报错:

Property 'logger' does not exist on type 'AbstractHttpAdapter<any, any, any>'.ts(2339)

已知可通过类型断言解决,但想了解是否有利用mock函数泛型的替代方案。


解决方案:给mock.method指定泛型匹配目标重载

可以通过给mock.method显式传入泛型参数,指定你实际使用的重载函数类型,让TypeScript正确推断调用参数的类型。

方式1:直接指定重载函数签名

import { LoggerService } from "@nestjs/common";
import { NestFactory, type NestApplicationOptions, type IEntryNestModule, type INestApplication } from "@nestjs/core";
import { equal } from "node:assert/strict";
import { suite, test } from "node:test";

suite("Example", async () => {
  test("How to type the override", async ({ mock }) => {
    // 显式指定泛型为第一个重载的函数类型
    const create = mock.method<
      (module: IEntryNestModule, options?: NestApplicationOptions) => Promise<INestApplication>
    >(NestFactory, "create", async () => ({}));

    // 此时arguments[1]会被正确推断为NestApplicationOptions | undefined
    equal(
      create.mock.calls[0].arguments[1]?.logger instanceof LoggerService,
      true,
    );
  })
})

方式2:提取重载类型别名简化写法

如果不想重复写函数签名,可以先从typeof NestFactory.create中提取第一个重载的类型:

import { LoggerService } from "@nestjs/common";
import { NestFactory, type NestApplicationOptions, type IEntryNestModule, type INestApplication } from "@nestjs/core";
import { equal } from "node:assert/strict";
import { suite, test } from "node:test";

// 从create的重载中提取第一个签名的类型
type CreateFirstOverload = typeof NestFactory.create extends {
  (module: IEntryNestModule, options?: NestApplicationOptions): Promise<INestApplication>;
  (...args: any[]): any;
} ? (module: IEntryNestModule, options?: NestApplicationOptions) => Promise<INestApplication> : never;

suite("Example", async () => {
  test("How to type the override", async ({ mock }) => {
    // 使用预定义的类型别名作为泛型
    const create = mock.method<CreateFirstOverload>(NestFactory, "create", async () => ({}));

    equal(
      create.mock.calls[0].arguments[1]?.logger instanceof LoggerService,
      true,
    );
  })
})

原理是mock.method的泛型参数允许你指定被Mock函数的具体类型签名,TypeScript会基于你指定的重载来推断Mock调用的参数类型,而非默认使用最后一个重载。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 19:15:01