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

升级至TS 5.3.0 + NestJS 9 + @nestjs/graphql 11后,PickType生成空GraphQL输入类型的问题求助

升级至TS 5.3.0 + NestJS 9 + @nestjs/graphql 11后,PickType生成空GraphQL输入类型的问题求助

大家好,我最近把项目技术栈做了升级,当前使用的版本组合是:

  • TypeScript 5.3.0(已开启"experimentalDecorators": true和"emitDecoratorMetadata": true)
  • NestJS v9 搭配 @nestjs/graphql@11.x
  • MikroORM v6 结合 MongoDB

之前在TS 4 + Nest 8 + @nestjs/graphql@10的环境下,我可以通过工具函数继承实体类,再用PickType(...)提取特定字段动态构建GraphQL更新输入类型,一切都正常。但升级之后,生成的输入类型居然完全是空的,连一个字段都没有,这可把我难住了。

先给大家展示我的代码结构:

Product 实体类

import { Entity, PrimaryKey, Property } from '@mikro-orm/core';
import { ObjectType, Field, ID } from '@nestjs/graphql';
import { IsString, IsNumber, IsBoolean } from 'class-validator';

@ObjectType()
@Entity({ tableName: 'product' })
export class Product {
  @Field(() => ID)
  @PrimaryKey()
  id!: string;

  @Field()
  @Property()
  @IsString()
  name!: string;

  @Field({ nullable: true })
  @Property({ nullable: true })
  @IsNumber()
  price?: number;

  @Field({ nullable: true })
  @Property({ nullable: true })
  @IsBoolean()
  available?: boolean;

  // …其他属性…
}

动态生成输入类型的工具函数

// src/utils/dto/create-update-input-type.ts
import { PartialType, PickType } from '@nestjs/graphql';
import { Type } from '@nestjs/common';

export function CreateUpdateInputType<
  E, K extends readonly (keyof E)[]
>(
  entityClass: Type<E>,
  keys: K,
): Type<Partial<Pick<E, K[number]>>> {
  return PartialType(PickType(entityClass, keys)) as any;
}

Product 的输入参数定义

// src/dto/product.args.ts
import { ArgsType, Field, InputType } from '@nestjs/graphql';
import { CreateUpdateInputType } from '@src/utils/dto';
import { Product } from '@src/entities/product.entity';
import { IsMongoId, IsOptional, ValidateNested } from 'class-validator';
import { Type } from 'class-transformer';

const updateFields = ['name', 'price', 'available'] as const;

@InputType()
class UpdateProductInput extends CreateUpdateInputType(
  Product,
  updateFields,
) {}

@ArgsType()
export class UpdateProductArgs {
  @Field()
  @IsMongoId()
  @IsOptional()
  id?: string;

  @Field(() => UpdateProductInput)
  @ValidateNested()
  @Type(() => UpdateProductInput)
  data!: UpdateProductInput;
}

我的 tsconfig 核心配置

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "CommonJS",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    // …其他配置项…
  }
}

问题现象对比

在升级前的TS 4 + Nest 8环境下,生成的GraphQL SDL完全符合预期:

input UpdateProductInput {
  name: String
  price: Float
  available: Boolean
}

但升级到新环境后,生成的SDL里输入类型完全是空的:

input UpdateProductInput

我实在搞不懂原因,明明满足这些前提:

  • Product类已经用@ObjectType()装饰
  • 每个要提取的字段都有对应的@Field()装饰器
  • updateFields是用as const声明的只读元组,类型定义正确
  • 我是在await app.init()之后才去查看SDL的

如果说是TS 5改变了装饰器元数据的继承逻辑,那直接对Product类调用PickType为什么也识别不到原类的字段呢?之前在Nest v11之前或者旧版TS里,完全不需要在子类上重新加@Field()就能正常生成输入类型啊。

有没有大佬知道@nestjs/graphql@11或者TypeScript 5.x里的某个变更,能解释这个运行时元数据丢失的问题?

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 08:13:01