I am having difficulty in mapping one object to another object in Type script especially when objects contain different types and properties
interface PassengerV1 {
firstName: string;
lastName: string;
address: Address;
temp1:strng;
temp2:string;
phoneNumbers: PhoneNumber[];
}
interface PassengerV2 {
firstName: string;
lastName: string;
address: Address;
}
interface ObjectA{
lossCause: string;
lossDate: string;
vehicleInformation: {
vehicle: [
{
passengerInformation: {
passenger: PassengerV1[];};
}
];
};
}
interface ObjectB{
lCause: string;
lDate: string;
vehicleInfo: {
vehicle: [
{
passengerInformation: {
passenger: PassengerV2[];
};
];
};
}
const requestData: ObjectB= {
lCause: ObjectA.lossCause,
lDate: ObjectA.lossDate,
vehicleInformation: vehicleInfo??
}
Above is the ObjectB, iam building from Object A but got stuck with vehicle information. Researched map, objectfromentries but not clear how can be applied with child types differ in properties?
Related
I have types:
type TUser= {
id: number,
name: string,
}
type TFields = {
value: number,
name: string,
otherField: string,
}
type TTask = {
id: number,
title: string,
}
type TDataMethod = {
"TField": "fields",
"TTask": "tasks",
}
base on this types, how i can create type something like that (the part of the Type below is pseudocode):
type TResponse<T> = {
data: T extends TUser ? TUser[] : {[TDataMethod[T]]: T}
time: string,
}
for objects
const userResponse: TResponse<TUser> = {
data: [
id: 1,
name: "John",
],
time: "13 august 2022"
}
const taskResponse: TResponse<TTask> = {
data: {
tasks: {
id: 1,
title: "Some task",
}
},
time: "14 august 2022"
}
or i have one way - use extends declaration?
It is possible with some Typescript "programming".
For example, I have these interfaces.
interface User {
name: string;
age: number;
}
interface Bot {
name: string;
author: string;
}
The Metadata should be an array so we could iterate from it.
type Metadata = [
{
name: 'users'; // here's the property
type: User; // here's the type
},
{
name: 'bots';
type: Bot;
}
];
We don't actually could iterate from it. So, create an helper named ArrayUnshift which will unshift (remove first item) from the generic type. If the generic type (Array) is [first, ...rest], then return the rest so the first item is removed.
type ArrayUnshift<Array extends any[]> =
Array extends [infer First, ...infer Rest] ?
Rest : never;
Then we could itearate the Metadata. If the first Metadata.type is equal to generic type, then return the Metadata.name, if not recursive to itself but unshift the Metadata.
type MetadataProperty<T extends any, Data extends any[] = Metadata> =
Data[0]['type'] extends T ?
Data[0]['name'] : MetadataProperty<T, ArrayUnshift<Data>>;
Last, create ResponseData with MetadataProperty<T> as its property.
interface ResponseData<T extends object> {
time: string;
data: MetadataProperty<T> extends string ? {
[Key in MetadataProperty<T>]: T;
} : {
string: T; // fallback to avoid error
}
}
There's a repo that related to this topic, take a look to Type Challenges.
EDIT: Or you could simply use Extract utility as being said by #caTS.
You don't need to "iterate" over them; just get the elements as a union and use Extract: Extract<Metadata[number], { type: T }>["name"].
Hi i'm struggling to create a type for networkConfig, i tried the following one but it's not working properly, notice that property is an Integer!!
type networkConfigType = {
number: {
name: string;
ethUsdPriceFeed: string;
};
};
const networkConfig = {
4: {
name : "rinkeby",
ethUsdPriceFeed: "0x8A753747A1Fa494EC906cE90E9f37563A8AF630e",
},
137: {
name: "polygon",
ethUsdPriceFeed: "0xF9680D99D6C9589e2a93a78A04A279e509205945",
},
};
type networkConfigType = Record<number, {
name: string;
ethUsdPriceFeed: string;
}>;
I've a dto called updateUserDTO and the class looks like this
#IsString()
full_name: string;
#IsNumber()
mobile: string;
#IsEmail()
email: string;
#IsOptional()
location: string;
#IsOptional()
landmark: string;
#IsOptional()
city: string;
How can I create a nested DTO, so when my response I post to my controller looks like this
{
"full_name": "xyz",
"mobile": 1231341451,
"email": "xyz#abc.com",
"address": {
"location": "new avenue",
"landmark": "Opp to St louis",
"city": "Buffalo"
}
}
you can use automapper to do that check the doc here :
https://automapperts.netlify.app/docs/nestjs
Just class-transformer for nested validation.
Divide you JSON into Parts
Do the use of class-transformer to validate a nested object
For Example
import { Type } from 'class-transformer';
import { IsDefined, IsNotEmptyObject, IsOptional, IsString,
ValidateNested } from 'class-validator';
// ################# Second Level Class #################
export class SecondLevel {
#IsOptional()
location: string;
#IsOptional()
landmark: string;
#IsOptional()
city: string;
}
// ############## First Level Class ###############
export class firstLevel {
#IsString()
full_name: string;
#IsNumber()
mobile: string;
#IsEmail()
email: string;
#IsDefined()
#IsNotEmptyObject()
#ValidateNested()
#Type(() => SecondLevel)
address: SecondLevel;
}
This question already has answers here:
How can I clone a JavaScript object except for one key?
(25 answers)
Closed 1 year ago.
I have two objects with two different types, I want to use one object to assign another.
interface From {
type: string;
timestamp: number;
aid?: string;
bid?: string;
cid?: string;
did?: string;
eid?: string;
fid?: string;
gid?: string;
}
interface To {
fromSocketID: string;
type: string;
timestamp: number;
aid?: string;
bid?: string;
cid?: string;
did?: string;
eid?: string;
fid?: string;
}
const from: From = {
type: "aaa",
timestamp: 1231231231,
gid: "ddd"
};
// Method1
const to1: To = {
fromSocketID: "temp",
type: from.type,
timestamp: from.timestamp
};
if (from.aid) {
to1.aid = from.aid
}
if (from.bid) {
to1.bid = from.bid;
}
if (from.cid) {
to1.cid = from.cid;
}
// ...three more if statements
// Method2
const to2: To = {
fromSocketID: "temp",
...from
}
// #ts-ignore
delete to2.gid;
interface To has a fromSocketID which From doesn't, and To lacks a gid property. In my real work scenario, I use Method1. I tried Method2, but i had to use ts-ignore. I wonder if there is a better solution.
You can use the rest operator to deconstruct the 'from', ignoring the gid property, like so:
interface From {
type: string;
timestamp: number;
aid?: string;
bid?: string;
cid?: string;
did?: string;
eid?: string;
fid?: string;
gid?: string;
}
interface To {
fromSocketID: string;
type: string;
timestamp: number;
aid?: string;
bid?: string;
cid?: string;
did?: string;
eid?: string;
fid?: string;
}
const from: From = {
type: "aaa",
timestamp: 1231231231,
gid: "ddd"
};
const { gid, ...rest } = from;
const to: To = {
fromSocketID: "temp",
...rest
};
I am using nest js in my sample application. I define the entity of my application .Entity means a document. But I struck at one place to define the location.
using mongoose I define the schema of my document like this see link
https://raw.githubusercontent.com/webmakaka/Node.js-API-Masterclass-With-Express-MongoDB/master/api/models/Bootcamp.js
location: {
// GeoJSON Point
type: {
type: String,
enum: ['Point']
},
coordinates: {
type: [Number],
index: '2dsphere'
},
formattedAddress: String,
street: String,
city: String,
state: String,
zipcode: String,
country: String
},
careers: {
// Array of strings
type: [String],
required: true,
enum: [
'Web Development',
'Mobile Development',
'UI/UX',
'Data Science',
'Business',
'Other'
]
},
same thing I want to do using typeorm using mongoDB without mongoos .can you please help me how I will do that.
here is my entity class
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, ManyToOne, ObjectID, ObjectIdColumn } from 'typeorm';
import { IsNotEmpty, MaxLength } from 'class-validator';
#Entity('bootcamp')
export class BootcampEntity extends BaseEntity {
#ObjectIdColumn() id: ObjectID;
#Column({type:'text',unique:true,length:50,nullable: false})
name:string;
#Column({type:'text'})
slug: string;
#Column({type:'text',length:500,nullable: false})
description: string;
#Column({type:'text'})
website: string;
#Column({type:'text',length:20})
phone: string;
#Column({type:'text',})
email: string;
#Column({type:'text',nullable: false})
address: string;
#Column({type:'text',array: true })
careers: string[];
#Column({type:'int'})
averageRating:number
#Column({type:'int'})
averageCost:number
//
#Column({type:'string',default:'no-photo.jpg'})
photo: string;
//
#Column({type:'boolean',default:false})
housing: boolean;
#Column({type:'boolean',default:false})
jobAssistance: boolean;
#Column({type:'boolean',default:false})
jobGuarantee: boolean;
#Column({type:'boolean',default:false})
acceptGi: boolean;
#Column({type:'date',default:Date.now()})
createdAt: Date;
}
I am using this framework
https://docs.nestjs.com/
typeorm link
https://typeorm.io/#/entities
there is schema
https://raw.githubusercontent.com/webmakaka/Node.js-API-Masterclass-With-Express-MongoDB/master/api/models/Bootcamp.js
I want make same schema using typeorm .I struck only defining the location attribute ?
how to define ?could you please tell me how I will define location in my entity class ?
I think location would have similar structure to code below.
source 1
source 2
enum GeoJSONPoint {
Point = "Point"
}
enum Careers {
WebDevelopment = 'Web Development',
MobileDevelopment = 'Mobile Development',
UIUX = 'UI/UX',
DataScience = 'Data Science',
Business = 'Business',
Other = 'Other'
}
#Entity('location')
export class LocationEntity extends BaseEntity {
#Column({
type: "enum",
enum: GeoJSONPoint
})
type: GeoJSONPoint;
#Column({type:'int'})
coordinates: number;
#Column({type:'text'})
formattedAddress: string;
#Column({type:'text'})
street: string;
#Column({type:'text'})
city: string;
#Column({type:'text'})
state: string;
#Column({type:'text'})
zipcode: string;
#Column({type:'text'})
country: string;
#Column({type:'simple-array'})
careers: Careers[];
}