错误类型“作业”不满足约束“文档<任何>”/错误类型上不存在属性“保存”

时间:2021-02-24 12:18:05

标签: node.js mongodb typescript mongoose nestjs

你能告诉我这里还有什么我可以调整的吗?

不管我做什么,它都不起作用。

提前致谢。

韩国

npm run start:dev
<块引用>

jobs-api@0.0.1 start:dev C:....\TypeScript\jobs-api 嵌套开始 --watch [12:43:14 PM] 在监视模式下开始编译...

src/jobs/jobs.service.ts:8:70 - error TS2344: Type 'Job' does not satisfy the constraint 'Document<any>'.
  Type 'Job' is missing the following properties from type 'Document<any>': $ignore, $isDefault, $isDeleted, $isEmpty, and 45 more.
src/jobs/jobs.service.ts:8:70 - error TS2344: Type 'Job' does not satisfy the constraint 'Document<any>'.
  Type 'Job' is missing the following properties from type 'Document<any>': $ignore, $isDefault, $isDeleted, $isEmpty, and 45 more.

8     constructor(@InjectModel('Job') private readonly jobModel: Model<Job>) {}
                                                                       ~~~

src/jobs/jobs.service.ts:15:29 - error TS2339: Property 'save' does not exist on type 'Job'.

15         return await newJob.save();
                               ~~~~

[12:48:24 PM] Found 2 errors. Watching for file changes.
[12:48:46 PM] File change detected. Starting incremental compilation...
src/jobs/jobs.service.ts:8:70 - error TS2344: Type 'Job' does not satisfy the constraint 'Document<any>'.
  Type 'Job' is missing the following properties from type 'Document<any>': $ignore, $isDefault, $isDeleted, $isEmpty, and 45 more.
[12:52:37 PM] File change detected. Starting incremental compilation...

src/jobs/interfaces/job.interface.ts:2:30 - error TS2503: Cannot find namespace 'mongoose'.

2 导出接口 Job extends mongoose.Document{ ~~~~~~~~~

src/jobs/interfaces/job.interface.ts:2:30 - error TS4022: 'extends' clause of exported interface 'Job' has or is using private name 'mongoose'.
[12:58:30 PM] File change detected. Starting incremental compilation...

src/jobs/jobs.service.ts:8:70 - error TS2344: Type 'Job' does not satisfy the constraint 'Document<any>'.
  Type 'Job' is missing the following properties from type 'Document<any>': $ignore, $isDefault, $isDeleted, $isEmpty, and 45 more.
[12:58:37 PM] Starting compilation in watch mode...

src/jobs/jobs.service.ts:8:70 - error TS2344: Type 'Job' does not satisfy the constraint 'Document<any>'.
  Type 'Job' is missing the following properties from type 'Document<any>': $ignore, $isDefault, $isDeleted, $isEmpty, and 45 more.

8     constructor(@InjectModel('Job') private readonly jobModel: Model<Job>) {}
                                                                       ~~~

src/jobs/jobs.service.ts:15:29 - error TS2339: Property 'save' does not exist on type 'Job'.

15         return await newJob.save();
                               ~~~~

[12:58:40 PM] Found 2 errors. Watching for file changes.


jobs.service.ts

import { Injectable } from '@nestjs/common';
import { Job } from './interfaces/job.interface';
import { Model, Document } from 'mongoose';
import { InjectModel } from '@nestjs/mongoose';

@Injectable()
export class JobsService {
    constructor(@InjectModel('Job') private readonly jobModel: Model<Job>) {}

    async find(id: string): Promise<Job> {
        return await this.jobModel.findOne({ _id: id});
    }
    async create(job: Job): Promise<Job> {
        const newJob = new this.jobModel(job);
        return await newJob.save();
    }
    async update(id: string, job: Job): Promise<Job> {
        return await this.jobModel.findByIdAndUpdate(id, job, { new: true });
    }
    async delete(id: string): Promise<Job> {
        return await this.jobModel.findByIdAndRemove(id);
    }


}

job.interface.ts


import {  Document } from 'mongoose';
export interface Job extends Document{
    id?: string;
    title: string;
    salary: number; 
}

package.json

  "name": "jobs-api",
  "version": "0.0.1",
  "description": "",
  "author": "",
  "private": true,
  "license": "UNLICENSED",
  "scripts": {
    "prebuild": "rimraf dist",
    "build": "nest build",
    "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
    "start": "nest start",
    "start:dev": "nest start --watch",
    "start:debug": "nest start --debug --watch",
    "start:prod": "node dist/main",
    "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
    "test": "jest",
    "test:watch": "jest --watch",
    "test:cov": "jest --coverage",
    "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
    "test:e2e": "jest --config ./test/jest-e2e.json"
  },
  "dependencies": {
    "@nestjs/common": "^7.5.1",
    "@nestjs/core": "^7.5.1",
    "@nestjs/mongoose": "^7.2.3",
    "@nestjs/platform-express": "^7.5.1",
    "mongoose": "^5.11.17",
    "reflect-metadata": "^0.1.13",
    "rimraf": "^3.0.2",
    "rxjs": "^6.6.3",
    "rxjs-compat": "^6.6.3"
  },
  "devDependencies": {
    "@nestjs/cli": "^7.5.1",
    "@nestjs/schematics": "^7.1.3",
    "@nestjs/testing": "^7.5.1",
    "@types/express": "^4.17.8",
    "@types/jest": "^26.0.15",
    "@types/node": "^14.14.6",
    "@types/supertest": "^2.0.10",
    "@typescript-eslint/eslint-plugin": "^4.6.1",
    "@typescript-eslint/parser": "^4.6.1",
    "eslint": "^7.12.1",
    "eslint-config-prettier": "7.2.0",
    "eslint-plugin-prettier": "^3.1.4",
    "jest": "^26.6.3",
    "prettier": "^2.1.2",
    "supertest": "^6.0.0",
    "ts-jest": "^26.4.3",
    "ts-loader": "^8.0.8",
    "ts-node": "^9.0.0",
    "tsconfig-paths": "^3.9.0",
    "typescript": "^4.0.5"
  },
  "jest": {
    "moduleFileExtensions": [
      "js",
      "json",
      "ts"
    ],
    "rootDir": "src",
    "testRegex": ".*\\.spec\\.ts$",
    "transform": {
      "^.+\\.(t|j)s$": "ts-jest"
    },
    "collectCoverageFrom": [
      "**/*.(t|j)s"
    ],
    "coverageDirectory": "../coverage",
    "testEnvironment": "node"
  }
}

jobs.controller.ts

import { Controller, Get, Post, Put, Delete, Param, Body } from '@nestjs/common';
import { JobsService } from './jobs.service';
import { JobDTO } from './dtos/job.dto';
import { Job } from './interfaces/job.interface';

@Controller('jobs')
export class JobsController {
    constructor (private readonly jobsService: JobsService) {}
    
    @Get(':id')
    find(@Param('id') id): Promise<Job> {
        return this.jobsService.find(id);
    }

    @Post()
    create(@Body() job: JobDTO): Promise<Job> {
        return this.jobsService.create(job);
    }

    @Put(':id')
    update(@Param('id') id, @Body() job: JobDTO): Promise<Job> {
        return this.jobsService.update(id, job);
    }

    @Delete(':id')
    delete(@Param('id') id): Promise<Job> {
        return this.jobsService.delete(id);
    }

}

1 个答案:

答案 0 :(得分:3)

第一个问题

架构的每个接口都必须扩展文档接口。 试试这个。

import { Document } from 'mongoose';
export interface Job extends Document {
    id?: string;
    title: string;
    salary: number; 
}

如果这不起作用,请将您的 package.json 添加到问题中

第二个问题:“JobDTO”类型的参数不能分配给“Job”类型的参数

要解决这个问题,只需将 DTO 设置为参数的类型。接口 Job 用于模型,不要用作函数的参数类型。请记住,如果您想创建某个文档,DTO 必须具有相同的属性,如果您想更新一个文档,您只需要一些属性即可。

import { Injectable } from '@nestjs/common';
import { Job } from './interfaces/job.interface';
import { Model, Document } from 'mongoose';
import { InjectModel } from '@nestjs/mongoose';

@Injectable()
export class JobsService {
    constructor(@InjectModel('Job') private readonly jobModel: Model<Job>) {}

    async find(id: string): Promise<Job> {
        return await this.jobModel.findOne({ _id: id});
    }
    async create(job: JobDTO): Promise<Job> { //JobDTO
        const newJob = new this.jobModel(job);
        return await newJob.save();
    }
    async update(id: string, job: JobDTO): Promise<Job> { //JobDTO
        return await this.jobModel.findByIdAndUpdate(id, job, { new: true });
    }
    async delete(id: string): Promise<Job> {
        return await this.jobModel.findByIdAndRemove(id);
    }


}

顺便说一句,我建议您创建一个不同的 DTO 进行更新,如下所示:

export class JobDTO { //Your normal DTO
    title!: string;
    salary!: number; 
}

export class UpdateJobDTO extends Partial<JobDTO> {} //Your Update DTO
//The Partial type converts all the properties of JobDTO to optional

让我知道这是否能解决您的问题;)