【问题标题】:error Type 'Job' does not satisfy the constraint 'Document<any> / error Property 'save' does not exist on type错误类型“作业”不满足约束“文档<any>/错误属性“保存”在类型上不存在
【发布时间】:2021-05-26 18:23:42
【问题描述】:

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

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

提前致谢。

韩国

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);
    }

}

【问题讨论】:

    标签: node.js mongodb typescript mongoose nestjs


    【解决方案1】:

    第一个问题

    模式的每个接口都必须扩展 Document 接口。 试试这个。

    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

    如果这能解决您的问题,请告诉我 ;)

    【讨论】:

    • 现在,新问题:error TS2345: Argument of type 'JobDTO' is not assignable to parameter of type 'Job'. Type 'JobDTO' is missing the following properties from type 'Job': $ignore, $isDefault, $isDeleted, $isEmpty, and 45 more. 17 return this.jobsService.create(job);
    • error TS2345: Argument of type 'JobDTO' is not assignable to parameter of type 'Job'. 22 return this.jobsService.update(id, job);
    • 更新答案,检查一下。
    猜你喜欢
    • 2021-06-21
    • 2019-12-26
    • 1970-01-01
    • 1970-01-01
    • 2020-07-07
    • 2020-02-24
    • 2021-01-28
    • 2020-10-25
    • 2018-10-25
    相关资源
    最近更新 更多