error TS2740 Type 'DeepPartial<Quiz>[]' is missing the following properties from type 'Question': id, question, hasId, save, and 4 more - javascript

I don't know how to fix this error. Does anyone know what I need to fix to get this code to work?
import { Injectable } from '#nestjs/common';
import { InjectRepository } from '#nestjs/typeorm';
import { CreateQuestionDto } from './dto/create-question.dto';
import { Question } from './question.entity';
import { QuestionRepository } from './question.repository';
#Injectable()
export class QuestionService {
constructor(
#InjectRepository(QuestionRepository)
private questionRepository: QuestionRepository,
) {}
async createQuestion(question: CreateQuestionDto): Promise<Question> {
return await this.questionRepository.save(question);
}
}
Returns the following error:
src/modules/quiz/question.service.ts:15:5 - error TS2740: Type 'DeepPartial[]' is missing the following properties from type 'Question': id, question, hasId, save, and 4 more.
15 return await this.questionRepository.save(question);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/modules/quiz/question.service.ts:15:47 - error TS2769: No overload matches this call.
Overload 1 of 4, '(entities: DeepPartial[], options?: SaveOptions): Promise<(DeepPartial & Quiz)[]>', gave the following error.
Argument of type 'CreateQuestionDto' is not assignable to parameter of type 'DeepPartial[]'.
Type 'CreateQuestionDto' is missing the following properties from type 'DeepPartial[]': length, pop, push, concat, and 29 more.
Overload 2 of 4, '(entity: DeepPartial, options?: SaveOptions): Promise<DeepPartial & Quiz>', gave the following error.
Type 'CreateQuestionDto' has no properties in common with type 'DeepPartial'.
15 return await this.questionRepository.save(question);
Question entity:
import { BaseEntity, Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
#Entity('questions')
export class Question extends BaseEntity {
#PrimaryGeneratedColumn()
id: string;
#Column({
type: 'varchar',
})
question: string;
}
Question repository:
import { EntityRepository, Repository } from 'typeorm';
import { Quiz } from './quiz.entity';
#EntityRepository(Quiz)
export class QuestionRepository extends Repository<Quiz> {}
CreateQuestion dto:
import { IsNotEmpty, Length } from 'class-validator';
export class CreateQuestionDto {
#IsNotEmpty()
#Length(3, 255)
question: string;
}
Question repository:
import { EntityRepository, Repository } from 'typeorm';
import { Quiz } from './quiz.entity';
#EntityRepository(Quiz)
export class QuestionRepository extends Repository<Quiz> {}

The problem is that your QuestionRepository is pointing to another entity (Quiz).
Change it to:
export class QuestionRepository extends Repository<Question> {}
That way you can avoid the any clause and use the dto directly on the save call.
async createQuestion(question: CreateQuestionDto): Promise<Question> {
return await this.questionRepository.save(question);
}

Related

Angular Behavior Subject multiple arguments

i need to get values from one component and get them in other one, i want to use behaviorSubject, but i dont get, how to pass 2 arguments in behaviorSubject, iam getting error TS2554: Expected 1 arguments, but got 2.
//service
import { Injectable } from '#angular/core';
import {BehaviorSubject} from 'rxjs';
#Injectable({
providedIn: 'root'
})
interface ICellSelection {
xId: number;
yId: number;
}
export class plotService {
public IdsForCellSelection: BehaviorSubject<ICellSelection> = new BehaviorSubject<ICellSelection>(null);
public setIdsForCellSelection(xItemIndex: number, yItemIndex: number) {
this.IdsForCellSelection.next(xItemIndex, yItemIndex);
}
constructor() { }
}
// component
public selectArea() {
this.store.dispatch(({ payload: [] }));
this.selectedItems = [this.xItem, this.yItem];
this.selectionChanged.emit(this.selectedItems);
//here iam trying to send 2 arguments+
this.plotService.setIdsForCellSelection( this.xItemIndex, this.yItemIndex);
}
BehaviourSubject takes one argument and you are trying to pass 2.
So below is not correct:
this.IdsForCellSelection.next(xItemIndex, yItemIndex);
Instead do this:
this.IdsForCellSelection.next({xItemIndex, yItemIndex});
Pass it around as an object of the defined type. Also if the default null isn't required, it'd be more suited to use ReplaySubject with buffer 1 instead of BehaviorSubject.
Service
import { Injectable } from '#angular/core';
import { ReplaySubject } from 'rxjs';
interface ICellSelection {
xId: number;
yId: number;
}
#Injectable({ providedIn: 'root' })
export class plotService {
public IdsForCellSelection: ReplaySubject<ICellSelection> = new ReplaySubject<ICellSelection>(1);
public setIdsForCellSelection(xItemIndex: number, yItemIndex: number) {
this.IdsForCellSelection.next(
{ xId: xItemIndex, yId: yItemIndex } as ICellSelection
);
}
constructor() { }
}
To maintain type coherence across the application, you'd need to define the type in an external file and import it where it's required.
Eg.
cell-selection.ts
export interface ICellSelection {
xId: number;
yId: number;
}
Component
import { ICellSelection } from './cell-selection';
...
public selectArea() {
this.store.dispatch(({ payload: [] }));
this.selectedItems = [this.xItem, this.yItem];
this.selectionChanged.emit(this.selectedItems);
this.plotService.setIdsForCellSelection({
xId: this.xItemIndex,
yId: this.yItemIndex
} as ICellSelection);
}
Service
import { Injectable } from '#angular/core';
import { ReplaySubject } from 'rxjs';
import { ICellSelection } from './cell-selection';
#Injectable({ providedIn: 'root' })
export class plotService {
public IdsForCellSelection: ReplaySubject<ICellSelection> = new ReplaySubject<ICellSelection>(1);
public setIdsForCellSelection(itemIndex: ICellSelection) {
this.IdsForCellSelection.next(itemIndex);
}
constructor() { }
}
you can also pass as an array, like so:
this.IdsForCellSelection.next([xItemIndex, yItemIndex, ..]);
suggestion
don't use an uppercase when naming a variable and use the '$' as a prefix for observables and subjects, it makes your code more readable throughout future developers
"idsForCellSelection$"

NestJS/TypeORM: Cannot read property 'createQueryBuilder' of undefined

Calling 'localhost:3000/contacts' (with or without parameters) at postman returns me this error and i don't know why. My backend is connected to a PostgreSQL db.
TypeError: Cannot read property 'createQueryBuilder' of undefined
at ContactsRepository.Repository.createQueryBuilder (...\Documents\Visual Studio Code Projects\funds-backend-nestjs\node_modules\typeorm\repository\Repository.js:17:29)
at ContactsRepository.getContacts (...\Documents\Visual Studio Code Projects\funds-backend-nestjs\dist\contacts\contacts.repository.js:17:34)
at ContactsService.getContacts (...\Documents\Visual Studio Code Projects\funds-backend-nestjs\dist\contacts\contacts.service.js:24:39)
at ContactsController.getContacts (...\Documents\Visual Studio Code Projects\funds-backend-nestjs\dist\contacts\contacts.controller.js:25:37)
at ...\Documents\Visual Studio Code Projects\funds-backend-nestjs\node_modules\#nestjs\core\router\router-execution-context.js:38:29
at processTicksAndRejections (internal/process/task_queues.js:93:5)
at async ...\Documents\Visual Studio Code Projects\funds-backend-nestjs\node_modules\#nestjs\core\router\router-execution-context.js:46:28
at async ...\Documents\Visual Studio Code Projects\funds-backend-nestjs\node_modules\#nestjs\core\router\router-proxy.js:9:17
My code looks like this:
#EntityRepository(Contact)
export class ContactsRepository extends Repository<Contact> {
async getContacts(filterDto: GetContactsFilterDto): Promise<Contact[]> {
const { name, search } = filterDto;
// const query = this.createQueryBuilder('contacts');
const query = await this.createQueryBuilder()
.select('contacts')
.from(Contact, 'contacts');
if (name) {
query.andWhere('contacts.name = :name', { name });
}
if (search) {
query.andWhere(
'(contacts.email LIKE :search OR contacts.telephone LIKE :search)',
{ search: `%${search}%` },
);
}
const contacts = await query.getMany();
return contacts;
}
import { BaseEntity, Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
#Entity({ name: 'contacts' })
export class Contact extends BaseEntity {
#PrimaryGeneratedColumn('uuid')
id: string;
#Column()
email: string;
#Column()
html_de: string;
#Column()
html_en: string;
#Column()
name: string;
#Column()
telephone: string;
}
export class ContactsController {
constructor(private contactsService: ContactsService) {}
#Get()
getContacts(
#Query(ValidationPipe) filterDto: GetContactsFilterDto,
): Promise<ContactDto[]> {
return this.contactsService.getContacts(filterDto);
}
#Injectable()
export class ContactsService {
constructor(
#InjectRepository(ContactsRepository)
private contactsRepository: ContactsRepository,
) {}
async getContacts(filterDto: GetContactsFilterDto): Promise<Contact[]> {
return this.contactsRepository.getContacts(filterDto);
}
import { Module } from '#nestjs/common';
import { TypeOrmModule } from '#nestjs/typeorm';
import { ContactsController } from './contacts.controller';
import { ContactsRepository } from './contacts.repository';
import { ContactsService } from './contacts.service';
#Module({
controllers: [ContactsController],
imports: [TypeOrmModule.forFeature([ContactsRepository])],
providers: [ContactsRepository, ContactsService],
exports: [ContactsRepository, ContactsService],
})
export class ContactsModule {}
Somebody know how i can fix this? Regards
ContactsRepository should only be used in the TypeOrmModule.forFeature() and not added to the providers or exports array. When it is added here, the injection token for ContactsRepository no longer points to the proper instance and Nest creates the class, but doesn't have it properly extend Repository as that code is all managed by TypeORM

NESTJS - How to send an object with an array and an object

i'm having a trouble with nest. What I want is a little bit difficult, and i don't know how to do that. First, with the ID of a site, I retrieve the users from this site and i want to be able to make a pagination, a sort by order (desc or asc i don't care) and to filtrate the results by value (a string). And in the output, i want to make an object with an array of the results and the synthesis. Example :
{
results : [{audit}],
syhthesis: {pageNumber: number, numberOfResults: number}
}
Honnestly, i've been trying for a while but i just cant understand how to do it. Here is my actual code :
the controller :
import { Controller, Get, Query, Param, Post, Body } from '#nestjs/common';
import { UserAuditService } from './user-audit.service';
import { UserAudit } from 'src/entities/user-audit.entity';
#Controller('useraudit')
export class UserAuditController {
constructor(private readonly userAuditService : UserAuditService){};
#Post("/userpersite/{:id}")
async getUsers(#Body()id: string, #Query('page') page: number): Promise<UserAudit[]>{
return this.userAuditService.getAuditsForSite(id, page)
}
}
the service :
import { Injectable } from '#nestjs/common';
import { InjectRepository } from '#nestjs/typeorm';
import { UserAudit } from '../entities/user-audit.entity';
import { Repository } from 'typeorm';
#Injectable()
export class UserAuditService {
constructor(
#InjectRepository(UserAudit)
private readonly userAuditRepository : Repository<UserAudit>
){}
async getAuditsForSite(_siteId : string, page: number = 1) : Promise<UserAudit[]>{
return this.userAuditRepository
.find({
join : {
alias : "user-audit",
innerJoinAndSelect: {
user : "user-audit.who"
}
},
where : {
site : _siteId
},
take: 10,
skip: 10 * (page -1)
})
}
}
and the entity :
import { Entity, Column, PrimaryGeneratedColumn, ManyToOne } from 'typeorm';
import { User } from './user.entity';
import { Site } from './site.entity';
#Entity('user-audit')
export class UserAudit {
#PrimaryGeneratedColumn()
id : string;
#ManyToOne(type => User, user => user.id)
who : User
#Column({ length : 100 })
action : string
#ManyToOne(type => Site, site => site.id)
site : Site
#Column({ type : 'date' })
date : Date
#Column({ length : 1000 })
before : string
#Column({ length : 1000 })
after : string
}
I have try many things in my controller, but now, i am stuck, i know i am missing something, perhaps a lot of things, so if someone can help me, it will be very thankful :)
In the UserAuditService you can use findAndCount instead of find. It will return an array with 2 elements. The first element will be the entities and the second will be the total count. Then you need to make the appropriate response object:
async getUsers(#Body()id: string, #Query('page') page: number): Promise<object>{
const [audits, total] = await this.userAuditService.getAuditsForSite(id, page)
return {
results : audits,
syhthesis: {
pageNumber: page,
numberOfResults: total,
}
}
sorry to bother you again. So i've tried it, and it doesn't work :/ I was certain this to be the solution. So I thought of something : to work with models, but again, i am stuck. Here is the new code :
the service :
import { Injectable } from '#nestjs/common';
import { InjectRepository } from '#nestjs/typeorm';
import { UserAudit } from '../entities/user-audit.entity';
import { Repository } from 'typeorm';
import { UserAuditRequest } from '../entities/user-audit-request';
#Injectable()
export class UserAuditService {
constructor(
#InjectRepository(UserAudit)
private readonly userAuditRepository : Repository<UserAudit>,
private readonly userRequest: Repository<UserAuditRequest>
){}
async getAuditsForSite(_siteId : string, page: number = 1, filter: any) : Promise<any>{
const joinAndSort = this.userAuditRepository
.findAndCount({
join : {
alias : "user-audit",
innerJoinAndSelect: {
user : "user-audit.who"
}
},
where : {
site : _siteId
},
take: 10,
skip: 10 * (page -1)
})
joinAndSort
const sortElement = this.userRequest.find({
where: {
pagination: page
}
})
sortElement
const filterElement = this.userRequest.findAndCount({
where: {
filter: filter
}
})
filterElement
}
}
the controller :
import { Controller, Get, Query, Param, Post, Body } from '#nestjs/common';
import { UserAuditService } from './user-audit.service';
import { UserAudit } from 'src/entities/user-audit.entity';
import { UserAuditRequest } from '../entities/user-audit-request';
import { ResultUserAudit } from '../entities/result-user-audit';
import { Any } from 'typeorm';
#Controller('useraudit')
export class UserAuditController {
constructor(private readonly userAuditService : UserAuditService, private readonly resultUserAudit: ResultUserAudit){};
#Post("/userpersite/:id")
async postUserPerSite(#Param()id: string,#Body() request : UserAuditRequest): Promise<ResultUserAudit>{
return await this.userAuditService.getAuditsForSite(id, request.pagination.pageNumber, request.filter);
the request model :
import { Injectable } from "#nestjs/common";
#Injectable()
export class UserAuditRequest {
constructor(){}
pagination: {
resultNumber: number;
pageNumber: number;
}
sort: {
columnSorted: any;
orderBy: any;
}
filter: {
columnFilter: any;
filtervalue: string;
}
}
and the result model :
import { Injectable } from "#nestjs/common";
import { UserAudit } from "./user-audit.entity";
#Injectable()
export class ResultUserAudit {
constructor(private userAudit: UserAudit){}
result: UserAudit[];
synthesis: {
pageNumber: number,
resultNumber: number;
}
}
I am trying to get the logic for my code, but i don't know, i just can't succed :( I see what i want to do as explain in my first post (hopefully) but i am not able to do it. I hope someone will be able to help and explain. Thank you :)

NestJS, TypeORM, can't fetch data

I am trying to get started with NestJS which uses TypeORM.
I have connected to a database. At least I think I have, because I was getting a lot of errors and after enough tuning of the config, the errors went away and the connection seems to be successful.
So now I want to fetch any bit of data just to get started.
There is a table in the database called RESULT_PAGE, so I just want to fetch any record from that. This is what I have tried:
result-page.entity.ts
import { Entity, PrimaryColumn, Column } from "typeorm";
#Entity()
export class ResultPage {
#PrimaryColumn()
result_page_id: number;
#Column({ length: 1 })
approval: string;
#Column({ length: 1})
manually_uploaded: string;
}
result-page.controller.ts
import { Controller, Get, Request } from '#nestjs/common';
import { ResultPageService } from './result-page.service';
#Controller('result-page')
export class ResultPageController {
constructor(
private resultPageService: ResultPageService
) { }
#Get('get-all')
getProfile() {
return this.resultPageService.findAll();
}
}
result-page.service.ts
import { Injectable } from '#nestjs/common';
import { InjectRepository } from '#nestjs/typeorm';
import { Repository } from 'typeorm';
import { ResultPage } from './result-page.entity';
#Injectable()
export class ResultPageService {
constructor(
#InjectRepository(ResultPage)
private readonly resultPageRepository: Repository<ResultPage>,
) {}
findAll(): Promise<ResultPage[]> {
return this.resultPageRepository.find();
}
}
If I edit the service to look like this:
import { Injectable } from '#nestjs/common';
import { InjectRepository } from '#nestjs/typeorm';
import { Repository } from 'typeorm';
import { ResultPage } from './result-page.entity';
#Injectable()
export class ResultPageService {
constructor(
#InjectRepository(ResultPage)
private readonly resultPageRepository: Repository<ResultPage>,
) {}
findAll(): Promise<string> {
return new Promise((resolve, reject) => { resolve('hello world') })
// return this.resultPageRepository.find();
}
}
then I get 'hello world', so it is definitely that the RESULT_PAGE table isn't connected
In the AppModule I am loading the entities like this
const typeOrmModuleOptions: TypeOrmModuleOptions = {
...
entities: [__dirname + '/**/*.entity{.ts,.js}'],
synchronize: true
}
I am sure that I am making some absolute noob mistake so if someone could help me out here it would be greatly appreciated. I am quite new to databases and api's so any info would help a lot. TIA
SOLVED
Solved by adding a connectString https://github.com/typeorm/typeorm/issues/3484#issuecomment-472315370
A little bit confusing the question. I miss the error and the database config.
result_page vs RESULT_PAGE: tablename
on linux/unix the tablenames are case sensitive, so you should set it in the annotation
#Entity({name: 'RESULT_PAGE'})
Please give some details to find the root cause if it was not that.

Type 'CanDeactivate' is not generic

Following the Angular 2 example here. There is can error right after the implements while running tsc:
error TS2315: Type 'CanDeactivate' is not generic.
import { Injectable } from '#angular/core';
import { CanDeactivate } from '#angular/router';
import { Observable } from 'rxjs/Observable';
export interface CanComponentDeactivate {
canDeactivate: () => boolean | Observable<boolean>;
}
#Injectable()
export class CanDeactivateGuard implements CanDeactivate<CanComponentDeactivate> {
canDeactivate(component: CanComponentDeactivate): Observable<boolean> | boolean {
return component.canDeactivate ? component.canDeactivate() : true;
}
}
This is confusing to me, as the interface has already been declared. Why do I see an error there?

Categories

Resources