打字稿:TS2739:缺少属性

时间:2021-01-25 12:27:50

标签: javascript typescript types typescript-typings

我在 Prisma 中有一对多的关系。

model Entity {
  id                     Int           @id @default(autoincrement())
  fields                 EntityField[]
  pageLayout             PageLayout[]
  Records                Records[]
  name                   String        @unique
  description            String?
  recordName             String
  recordDatatype         Int           @default(0)
  allowReporting         Boolean       @default(false)
  allowTrackFieldHistory Boolean       @default(false)
  status                 Boolean       @default(false)
  isSearchable           Boolean       @default(true)
  createdAt              DateTime      @default(now())
  updatedAt              DateTime      @default(now()) @updatedAt

}

model EntityField {
  id           Int       @id @default(autoincrement())
  entityId     Int
  entity       Entity    @relation(fields: [entityId], references: [id])
  Records      Records[]
  name         String
  label        String?
  type         Int
  data         Json?
  description  String?
  helpText     String?
  isRequired   Boolean   @default(false)
  defaultValue String?
  createdAt    DateTime  @default(now())
  updatedAt    DateTime  @default(now()) @updatedAt
}

model Records {
  id       Int         @id @default(autoincrement())
  entity   Entity      @relation(fields: [entityId], references: [id])
  entityId Int
  field    EntityField @relation(fields: [fieldId], references: [id])
  fieldId  Int
  value    Json?
  createdAt   DateTime @default(now())
  updatedAt   DateTime @default(now()) @updatedAt
}

和 graphql 的解析器,具有这样的存储库等:

RecordResolver:

import { Arg, Mutation, Resolver } from 'type-graphql';

import { PrismaClient } from '@prisma/client';

import { Record } from '../types';
import { CreateRecordInput } from '../inputs';
import RecordRepository from '../../db/repository/recordRepository';

@Resolver(() => Record)
export default class RecordResolver {
  db: PrismaClient;

  recordRepo: RecordRepository;

  constructor() {
    this.db = new PrismaClient();
    this.recordRepo = new RecordRepository();
  }

  @Mutation(() => Record)
  async createRecord(@Arg('data', { validate: true }) i: CreateRecordInput): Promise<Record> {
    const id = await this.db.records.findFirst({ where: { id: i.entityId } });
    console.log('yellow');
    if (id !== null) {
      throw new Error('ID needs to be unique');
    }

    const entity = await this.db.entity.findFirst({ where: { id: i.entityId } });
    if (entity === null) {
      throw new Error('Entity does not exist');
    }

    return this.recordRepo.create(i);
  }
}

recordRepository:

import { Prisma, PrismaClient, PromiseReturnType } from '@prisma/client';
import mapper from '../../lib/mapper';

import { Record } from '../../graphql/types';
import { CreateRecordInput } from '../../graphql/inputs';
import { RecordDto } from '../../dto';
import IRepository from './IRepository';

import RecordsInclude = Prisma.RecordsInclude;

export default class RecordRepository implements IRepository<Record> {
  private readonly client: PrismaClient;

  private readonly mandatoryRelationships: RecordsInclude;

  constructor() {
    this.client = new PrismaClient();
    this.mandatoryRelationships = {
      entity: true,
      field: true,
    };
  }

  create = async (item: CreateRecordInput): Promise<RecordDto> => {
    const record = await this.client.records.create({
      data: {
        ...item,
      },
      include: this.mandatoryRelationships,
    });

    return this.makeDTO(record);
  };

  makeDTO = (record: any): RecordDto => mapper.map(record, RecordDto, Record);

记录输入:

import { InputType, Field, Int } from 'type-graphql';
import { IsInt } from 'class-validator';
import { GraphQLJSONObject } from 'graphql-type-json';

import { InputJsonValue } from '@prisma/client';
import { Record } from '../types';

@InputType()
export default class CreateRecordInput implements Partial<Record> {
  @Field(() => Int)
  @IsInt()
  entityId!: number;

  @Field(() => Int)
  @IsInt()
  fieldId!: number;

  @Field(() => GraphQLJSONObject)
  value!: InputJsonValue;
}

记录类型:

import { Field, ObjectType, Int } from 'type-graphql';
import { GraphQLJSONObject } from 'graphql-type-json';

import { AutoMap } from '@automapper/classes';
import { InputJsonValue } from '@prisma/client';

@ObjectType({ description: 'Records of an object' })
export default class Record {
  @AutoMap()
  @Field(() => Int)
  id!: number;

  @AutoMap()
  @Field(() => GraphQLJSONObject)
  value!: InputJsonValue;

  @AutoMap()
  @Field(() => Date)
  createdAt!: Date;

  @AutoMap()
  @Field(() => Date)
  updatedAt!: Date;
}

当我运行服务器时,我得到:

TSError: ⨯ Unable to compile TypeScript:
src/db/repository/recordRepository.ts:26:7 - error TS2739: Type '{ entityId: number; fieldId: number; value: InputJsonValue; }' is missing the following properties from type 'RecordsCreateInput': entity, field

26       data: {
         ~~~~

  node_modules/@prisma/client/index.d.ts:2287:5
    2287     data: RecordsCreateInput
             ~~~~
    The expected type comes from property 'data' which is declared here on type 'Subset<RecordsCreateArgs, RecordsCreateArgs>'

    at createTSError (/home/programmer/projects/crm-api/node_modules/ts-node/src/index.ts:513:12)
    at reportTSError (/home/programmer/projects/crm-api/node_modules/ts-node/src/index.ts:517:19)
    at getOutput (/home/programmer/projects/crm-api/node_modules/ts-node/src/index.ts:752:36)
    at Object.compile (/home/programmer/projects/crm-api/node_modules/ts-node/src/index.ts:968:32)
    at Module.m._compile (/home/programmer/projects/crm-api/node_modules/ts-node/src/index.ts:1056:42)
    at Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
    at Object.require.extensions.<computed> [as .ts] (/home/programmer/projects/crm-api/node_modules/ts-node/src/index.ts:1059:12)
    at Module.load (internal/modules/cjs/loader.js:928:32)
    at Function.Module._load (internal/modules/cjs/loader.js:769:14)
    at Module.require (internal/modules/cjs/loader.js:952:19)
[nodemon] app crashed - waiting for file changes before starting...

我在这里遗漏了什么?

1 个答案:

答案 0 :(得分:0)

记录存储库创建方法缺少字段和实体的关系:

create = async (item: CreateRecordInput): Promise<RecordDto> => {
    const record = await this.client.records.create({
      data: {
        ...item,
      },
      include: this.mandatoryRelationships,
    });

    return this.makeDTO(record);
  };

问题已修复。