interface TestObject {
person: {
firstName: string;
lastName: string;
address: {
country: string;
city: string;
street: string;
}
}
id: string;
}
const t: TestObject = {} as any;
type K<T> = T extends object ? keyof T : never;
function f<T, K1 extends K<T>>(object: T, key: K1): T[K1];
function f<T, K1 extends K<T>, K2 extends K<T[K1]>>(object: T, key1: K1, key2: K2): T[K1][K2];
function f<T, K1 extends K<T>, K2 extends K<T[K1]>, K3 extends K<T[K1][K2]>>(object: T, key1: K1, key2: K2, key3: K3): T[K1][K2][K3];
// ...
function f() {
return 1 as any;
}
const result1 = f(t, 'person', 'address');
/*
const result1: {
country: string;
city: string;
street: string;
}
*/
const result2 = f(t, 'id', '');
/*
Argument of type 'string' is not assignable to parameter of type 'never'.ts(2345)
*/
Can the same be done without "death by a thousand overloads"? If there was something like Tail<T> type alias for const tuples, i think i know how i could do it.
Related
In my products schema, the product information is kept in a separate object. In the code below, I am trying to fetch all the products with the trademark Apple, but the code does not work.
async getProductWithStore(productInfoDto: ProductInfoDto) {
try {
const product = await this.productModel
.find({productInfo: productInfoDto})
.populate('store')
return product;
} catch (err) {
return err;
}
}
Here is the request
productInfo.dto.ts
import { IsNotEmpty, IsOptional } from "class-validator";
export class ProductInfoDto {
#IsNotEmpty()
trademark: string;
#IsOptional()
releaseYear: string;
#IsOptional()
model: string;
#IsOptional()
size: string;
#IsOptional()
gender: string;
#IsOptional()
ram: string;
#IsOptional()
screenSize: string;
#IsOptional()
storage: string;
}
product.schema.ts
import { Document, Types } from 'mongoose';
import {Prop, Schema, SchemaFactory} from '#nestjs/mongoose';
import {Store} from '../../store/schemas/store.schema';
import { Category } from 'src/category/schemas/category.schema';
import { ProductInfoDto } from '../dto/product-info.dto';
export type ProductDocument = Product & Document;
#Schema({timestamps:true})
export class Product {
#Prop({required: true})
productName: string;
#Prop({required: true})
description: string;
#Prop({required:true})
stock: number;
#Prop({required:true, type: Types.ObjectId, ref:'Category'})
category: Category;
#Prop({required:true, type:Object})
productInfo: ProductInfoDto
#Prop({required:true})
image:string;
#Prop({required:true, type: Types.ObjectId, ref:'Store'})
store: Store;
#Prop()
sales: number;
#Prop()
rating: number;
#Prop([String])
comments: string[]
}
export const ProductSchema = SchemaFactory.createForClass(Product);
I tried a lot of things from manually typing the information into the code but none of them worked
I found the solution
I replaced the .find code with the code below
async getProductWithStore(productInfoDto: ProductInfoDto) {
try {
const product = await this.productModel
.find({'productInfo.trademark':"Apple"})
return product;
}catch(err){
return err
}
}
I have interface
IUser {
name: string;
surname: string;
cityLocation: string;
}
the value will be
const user: IUser = {
"name": "John";
"surname": "Smith";
"cityLocation": "LA";
}
I have adapter, they have method which receive
function adapter(columns: { [key: string]: string }) {...}
when I try to do:
adapter(user);
I have error:
Argument of type 'IUser' is not assignable to parameter of type '{ [key: string]: string; }'. Index signature is missing in type 'IUser'.
How can I fix it?
(funny, but when I dont use signature IUser for object user - adapter works...)
Hope for your help. Big Thx!
As the error says, Index signature is missing in type 'IUser' so add it:
interface IUser {
name: string;
surname: string;
cityLocation: string;
[key: string]: string;
}
Playground link
I have the following interface for model schema:
import { Document } from 'mongoose';
export interface ILog {
tags: { [key: string]: string }[];
}
export interface ILogDocument extends ILog, Document {}
And there is the schema:
const logSchema = new Schema<ILogDocument>({
tags: { type: Map, of: String },
});
So i get the following type error on my schema:
TS2322: Type '{ type: MapConstructor; of: StringConstructor; }' is not assignable to type 'SchemaDefinitionProperty<{ [key: string]: string; }[]> | undefined'.
I want to use proper type defintion, I tried type: Schema.Types.Mixed and its works, but is there a better way to specify mongoose type for tags: { [key: string]: string }[] ?
{ [key: string]: string }[] is not exactly Map. You can use the Map type from TS.
import { Document, Schema } from 'mongoose';
export interface ILog {
tags: Map<string, string>;
}
export interface ILogDocument extends ILog, Document {}
const logSchema = new Schema<ILogDocument>({
tags: { type: Map, of: String }
});
I'm trying to update my Postgres database using Prisma ORM in NestJS (Microservices architecture).
The code allows users to interact with invitation requests.
But I keep getting the error:
Argument of type 'Invitation' is not assignable to parameter of type 'Invitation & { work: Work; }'. Property 'work' is missing in type 'Invitation' but required in type '{ work: Work; }'.
The Full error message looks like this:
Type '{ status: "PENDING" | "ACCEPTED" | "REJECTED"; work: undefined; id: string; workId: string; coId?: string; createdAt: Date; respondedAt?: Date; owner?: string; note?: string; }' is not assignable to type '(Without<InvitationUpdateInput, InvitationUncheckedUpdateInput> & InvitationUncheckedUpdateInput) | (Without<...> & InvitationUpdateInput)'.
Type '{ status: "PENDING" | "ACCEPTED" | "REJECTED"; work: undefined; id: string; workId: string; coId?: string; createdAt: Date; respondedAt?: Date; owner?: string; note?: string; }' is not assignable to type 'Without<InvitationUncheckedUpdateInput, InvitationUpdateInput> & InvitationUpdateInput'.
Type '{ status: "PENDING" | "ACCEPTED" | "REJECTED"; work: undefined; id: string; workId: string; coId?: string; createdAt: Date; respondedAt?: Date; owner?: string; note?: string; }' is not assignable to type 'Without<InvitationUncheckedUpdateInput, InvitationUpdateInput>'. Types of property 'workId' are incompatible. Type 'string' is not assignable to type 'never'.
How can I fix this?
Thanks in advance!
The Invitation Interface:
export default class Invitation {
id: string;
workId: string;
work: string;
co?: string;
status: RequestStatus;
createdAt: Date;
respondedAt?: Date;
owner?: string;
note?: string;
}
export enum RequestStatus {
PENDING = 'PENDING',
REJECTED = 'REJECTED',
ACCEPTED = 'ACCEPTED',
}
The prisma invitation schema:
model Invitation {
id String #id #db.Uuid
workId String #db.Uuid
work Work #relation(...)
status RequestStatus
co String #db.Uuid
owner String
note String
createdAt DateTime
respondedAt DateTime
}
The Updating mechanics in Postgres Persistence Infrastructure:
async update(invitation: Invitation): Promise<Invitation> {
const entity = await this.prismaService.invitation.update({
where: {
id: invitation.id,
},
data: {
...invitation,
status: RequestStatusEntity[invitation.status],
work: undefined,
},
include: {
work: true,
},
});
return this.toDomain(entity);
}
private toDomain(
entity: InvitationEntity & {
work: WorkEntity;
},
): Invitation {
return Object.setPrototypeOf(
{
...entity,
status: RequestStatus[entity.status],
},
Invitation.prototype,
);
}
You cannot use TypeScript enums in this case as Prisma uses string literals in the generated type.
I would suggest using Prisma's types directly instead of creating your own like this:
import { RequestStatus } from '#prisma/client'
export default class Invitation {
id: string;
workId: string;
work: string;
co?: string;
status: RequestStatus;
createdAt: Date;
respondedAt?: Date;
owner?: string;
note?: string;
}
I have a service in an application that was previously working but all of a sudden I am getting this typescript error and I am unsure how to go about solving it. Please see my model file:
import mongoose from "mongoose";
import { AccessType, TicketType } from "./types";
interface TicketAttrs {
name: string;
type: TicketType;
access: AccessType;
uniqueId: string;
price: number;
quantity: number;
creator: string;
}
interface TicketDoc extends mongoose.Document {
name: string;
type: TicketType;
access: AccessType;
uniqueId: string;
price: number;
quantity: number;
creator: string;
}
interface TicketModel extends mongoose.Model<TicketDoc> {
build(attrs: TicketAttrs): TicketDoc;
}
const ticketSchema = new mongoose.Schema(
{
name: {
type: String,
},
type: {
type: String,
enum: Object.values(TicketType),
},
access: {
type: String,
enum: Object.values(AccessType),
},
price: {
type: Number,
},
uniqueId: {
type: String,
},
quantity: {
type: Number,
},
creator: {
type: String,
},
},
{
timestamps: true,
toJSON: {
transform(doc, ret) {
ret.id = ret._id;
delete ret._id;
},
},
}
);
ticketSchema.statics.build = (attrs: TicketAttrs) => {
return new Ticket(attrs);
};
const Ticket = mongoose.model<TicketDoc, TicketModel>("Ticket", ticketSchema);
export { Ticket };
I get an error on ticketSchema on this line const Ticket = mongoose.model<TicketDoc, TicketModel>("Ticket", ticketSchema);
The Error Message is:-
const ticketSchema: mongoose.Schema<mongoose.Document<any>, mongoose.Model<mongoose.Document<any>>>
No overload matches this call.
Overload 1 of 6, '(name: string, schema?: Schema<TicketDoc, TicketModel> | undefined, collection?: string | undefined, skipInit?: boolean | undefined): TicketModel', gave the following error.
Argument of type 'Schema<Document<any>, Model<Document<any>>>' is not assignable to parameter of type 'Schema<TicketDoc, TicketModel>'.
Types of property 'methods' are incompatible.
Type '{ _id?: any; __v?: number | undefined; $ignore: (path: string) => void; $isDefault: (path: string) => boolean; $isDeleted: (val?: boolean | undefined) => boolean; $isEmpty: (path: string) => boolean; ... 47 more ...; validateSync: (pathsToValidate?: string[] | undefined, options?: any) => NativeError | null; } & { ....' is not assignable to type '{ name: string; type: TicketType; access: AccessType; uniqueId: string; price: number; quantity: number; creator: string; _id?: any; __v?: number | undefined; $ignore: (path: string) => void; ... 50 more ...; validateSync: (pathsToValidate?: string[] | undefined, options?: any) => NativeError | null; } & { ...; }'.
Type '{ _id?: any; __v?: number | undefined; $ignore: (path: string) => void; $isDefault: (path: string) => boolean; $isDeleted: (val?: boolean | undefined) => boolean; $isEmpty: (path: string) => boolean; ... 47 more ...; validateSync: (pathsToValidate?: string[] |
I am also getting an error saying that there is no build function, I don't understand what broke the code and it was working without any changes.