最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

How to convert typescript class to plain javascript object with class-transformer - Stack Overflow

programmeradmin4浏览0评论

I've some typescript classes instances in my angular app that I've to save to firebase. Firebase isn't supporting custom classes, so I found this: that seems well fitted for me.

So now I'm creating my object, and trying to convert it.

Here is my object.

export class Trip {
  id: string;
  owner: string;
  name: string;
  @Type(() => Date)
  startDate: Date;
  @Type(() => Date)
  endDate: Date | undefined;
  coverImageUrl: string;

  @Type(() => Itinerary)
  itinerary: Itinerary;

  constructor() {
    this.itinerary = new Itinerary();
  }
}

export class Itinerary {
  @Type(() => ItineraryStats)
  stats: ItineraryStats;
  @Type(() => Step, {
    discriminator: {
      property: '__type',
      subTypes: [
        { value: ActivityStep, name: 'ActivityStep' },
        { value: NightStep, name: 'NightStep' },
        { value: PointOfInterest, name: 'PointOfInterest' },
        { value: TravelStep, name: 'TravelStep' },
      ],
    },
  })
  steps: Step[];

  constructor() {
    this.steps = Step[0];
    this.stats = new ItineraryStats();
  }
}

export class ItineraryStats {
  ///In days
  duration: number;
  //in hours
  driveTime: number;
  //in kilometers
  driveDistance: number;

  averageDriveDistancePerDay(): number {
    return this.driveDistance / this.duration;
  }
  averageDriveTimePerDay(): number {
    return this.driveTime / this.duration;
  }
}


export abstract class Step {
  @Type(() => Date)
  start: Date;

  @Type(() => Date)
  end: Date;
  duration: number;
  enforcedStartStop: boolean;
  warning: string;
}

export class ActivityStep extends StopStep {
  duration: number;

  constructor() {
    super();
    this.id = Guid.newGuid();
  }
}


export class NightStep extends StopStep {
  nightNumber: number;
  numberOfNight: number;
}

export class PointOfInterest {
  @Type(()=>PointOfInterest)
  type: PointOfInterest;
}


export class TravelStep extends Step {
  @Type(() => TravelMode)
  Mode: TravelMode;
  PolyLines: string;
}

I'm creating one "trip" and trying to convert it:

const trip = new Trip();
trip.owner= firebase.auth().currentUser.uid;
trip.name= action.name;
trip.startDate = action.startDate,
trip.endDate = action.endDate;
console.log(trip);
const converted = classToPlain(trip)

But I get this:

ERROR TypeError: Cannot read property 'constructor' of undefined
    at TransformOperationExecutor.js:207
    at Array.find (<anonymous>)
    at TransformOperationExecutor.transform (TransformOperationExecutor.js:207)
    at TransformOperationExecutor.transform (TransformOperationExecutor.js:266)
    at ClassTransformer.classToPlain (ClassTransformer.js:10)
    at classToPlain (index.js:8)
    at Object.toFirestore (trips.firestore.ts:16)
    at ma (index.cjs.js:15983)
    at n.set (index.cjs.js:15359)
    at AngularFirestoreDocument.set (angular-fire-firestore.js:512)

The object I just created:

I guess either my object is in an improper state or I've something poorly defined, but I can't find what?

I've some typescript classes instances in my angular app that I've to save to firebase. Firebase isn't supporting custom classes, so I found this: https://github./typestack/class-transformer that seems well fitted for me.

So now I'm creating my object, and trying to convert it.

Here is my object.

export class Trip {
  id: string;
  owner: string;
  name: string;
  @Type(() => Date)
  startDate: Date;
  @Type(() => Date)
  endDate: Date | undefined;
  coverImageUrl: string;

  @Type(() => Itinerary)
  itinerary: Itinerary;

  constructor() {
    this.itinerary = new Itinerary();
  }
}

export class Itinerary {
  @Type(() => ItineraryStats)
  stats: ItineraryStats;
  @Type(() => Step, {
    discriminator: {
      property: '__type',
      subTypes: [
        { value: ActivityStep, name: 'ActivityStep' },
        { value: NightStep, name: 'NightStep' },
        { value: PointOfInterest, name: 'PointOfInterest' },
        { value: TravelStep, name: 'TravelStep' },
      ],
    },
  })
  steps: Step[];

  constructor() {
    this.steps = Step[0];
    this.stats = new ItineraryStats();
  }
}

export class ItineraryStats {
  ///In days
  duration: number;
  //in hours
  driveTime: number;
  //in kilometers
  driveDistance: number;

  averageDriveDistancePerDay(): number {
    return this.driveDistance / this.duration;
  }
  averageDriveTimePerDay(): number {
    return this.driveTime / this.duration;
  }
}


export abstract class Step {
  @Type(() => Date)
  start: Date;

  @Type(() => Date)
  end: Date;
  duration: number;
  enforcedStartStop: boolean;
  warning: string;
}

export class ActivityStep extends StopStep {
  duration: number;

  constructor() {
    super();
    this.id = Guid.newGuid();
  }
}


export class NightStep extends StopStep {
  nightNumber: number;
  numberOfNight: number;
}

export class PointOfInterest {
  @Type(()=>PointOfInterest)
  type: PointOfInterest;
}


export class TravelStep extends Step {
  @Type(() => TravelMode)
  Mode: TravelMode;
  PolyLines: string;
}

I'm creating one "trip" and trying to convert it:

const trip = new Trip();
trip.owner= firebase.auth().currentUser.uid;
trip.name= action.name;
trip.startDate = action.startDate,
trip.endDate = action.endDate;
console.log(trip);
const converted = classToPlain(trip)

But I get this:

ERROR TypeError: Cannot read property 'constructor' of undefined
    at TransformOperationExecutor.js:207
    at Array.find (<anonymous>)
    at TransformOperationExecutor.transform (TransformOperationExecutor.js:207)
    at TransformOperationExecutor.transform (TransformOperationExecutor.js:266)
    at ClassTransformer.classToPlain (ClassTransformer.js:10)
    at classToPlain (index.js:8)
    at Object.toFirestore (trips.firestore.ts:16)
    at ma (index.cjs.js:15983)
    at n.set (index.cjs.js:15359)
    at AngularFirestoreDocument.set (angular-fire-firestore.js:512)

The object I just created:

I guess either my object is in an improper state or I've something poorly defined, but I can't find what?

Share Improve this question asked Mar 9, 2021 at 19:51 J4NJ4N 20.8k42 gold badges222 silver badges384 bronze badges 3
  • Please share Type decorator – captain-yossarian from Ukraine Commented Mar 15, 2021 at 13:33
  • @captain-yossarian this decorator is from the library I linked: github./typestack/class-transformer/blob/develop/src/… – J4N Commented Mar 15, 2021 at 14:52
  • 1 You should create a Minimal, Reproducible Example – TmTron Commented Mar 15, 2021 at 19:20
Add a ment  | 

1 Answer 1

Reset to default 2 +200

The error lies in the definition of Itinerary, more specifically the code line this.steps = Step[0]; which sets the variable to undefined and most likely wasn't intentional. The class-transformer library can deal with property steps being an empty array, array of steps, or not existing in the first place but crashes when the value is set to undefined.

export class Itinerary {
  @Type(() => ItineraryStats)
  stats: ItineraryStats;
  @Type(() => Step, {
    discriminator: {
      property: '__type',
      subTypes: [
        { value: ActivityStep, name: 'ActivityStep' },
        { value: NightStep, name: 'NightStep' },
        { value: PointOfInterest, name: 'PointOfInterest' },
        { value: TravelStep, name: 'TravelStep' },
      ],
    },
  })
  steps: Step[];

  constructor() {
    // Step[0] causes the crash, because its undefined, either dont set it or 
    // set it to this.steps = []
    this.steps = Step[0]; 
    this.stats = new ItineraryStats();
  }
}

More details: Due to the use of discriminators on property steps the corresponding logic kicked in and pared the constructors defined under subTypes, with the constructor of the current value to find the correct subtype name:

    if (this.transformationType === TransformationType.CLASS_TO_PLAIN) {
      subValue[targetType.options.discriminator.property] = targetType.options.discriminator.subTypes.find(
        subType => subType.value === subValue.constructor
      ).name;
    }

link to github

Step[0] being undefined eventually made this line subValue.constructor crash.

发布评论

评论列表(0)

  1. 暂无评论