项目在本地开发和测试环境均正常,但在部署时,应用启动失败,日志报错:
bash
src/devices/devices.service.ts:14:7 - error TS2322: Type 'string' is not assignable to type 'never'.
报错位置为:
ts
// devices.service.ts
return this.prisma.device.create({
createDeviceDto, // 报错指向这一行
});
经过
检查代码发现,CreateDeviceDto
中定义了 deviceGroupId
字段:
ts
// create-device.dto.ts
export class CreateDeviceDto {
@IsString()
name: string;
@IsIP()
ipAddress: string;
@IsUUID()
@IsOptional()
deviceGroupId?: string; // 类型为 string
}
对应的 Prisma 模型为:
prisma
model Device {
id String
name String
deviceGroupId String?
deviceGroup DeviceGroup? @relation(fields: [deviceGroupId], references: [id])
}
查看 Prisma 生成的类型定义:
ts
// node_modules/.prisma/client/index.d.ts
export type DeviceCreateInput = {
name: string;
ipAddress: string;
deviceGroupId?: never; // 注意:类型是 never
deviceGroup?: { connect: { id: string } };
};
原因定位 :
Prisma 在 6.x 版本中,对于通过 @relation(fields: [...])
定义的外键字段,在创建输入类型中将其标为 never
,防止直接赋值。必须通过关系字段 deviceGroup.connect
的方式建立关联。
处理方案
方案一:修改 DTO,使用关系字段(推荐)
ts
export class CreateDeviceDto {
@IsString()
name: string;
@IsIP()
ipAddress: string;
@ValidateNested()
@Type(() => DeviceGroupConnectDto)
@IsOptional()
deviceGroup?: { connect: { id: string } };
}
class DeviceGroupConnectDto {
@IsString()
@IsUUID()
id: string;
}
前端传参格式:
json
{
"name": "web-server",
"ipAddress": "192.168.1.10",
"deviceGroup": {
"connect": {
"id": "cmg_abc123"
}
}
}
Service 层直接透传:
ts
return this.prisma.device.create({
createDeviceDto,
});
方案二:保持 DTO 不变,在 Service 中转换
ts
const { deviceGroupId, ...rest } = createDeviceDto;
return this.prisma.device.create({
{
...rest,
deviceGroup: deviceGroupId ? { connect: { id: deviceGroupId } } : undefined,
}
});
最终选择
项目为新系统,MVP 刚完成,前端尚未正式对接,无历史兼容压力。
因此,选择方案一:修改 DTO,使用 deviceGroup.connect
模式。
选择理由:
- 符合 Prisma 推荐的最佳实践
- 类型系统完全对齐,避免后续类似问题
- 为后续支持
create
、connectOrCreate
等操作预留扩展性 - 从一开始就建立统一的关联处理规范,利于团队协作
结果
重新部署后,TypeScript 编译通过,应用正常启动,设备创建功能验证无误。
后续其他模块的关联字段均按此模式统一处理。
#Prisma #NestJS #TypeScript #Deployment #TypeNever #TypeError #数据库关联