0

Just imagine I have 2 html tables next to each other. Each table has an array of unassigned pupils or assigned pupils for a certain test. With 2 buttons you can move those checkbox-selected pupils to the other html table.

The pupils in both html tables have nearly the same properties.

When I use Object.Assign then I get an compile error:

properties gradeScorePairs is missing in type {} and UnAssignedPupil

To fix that error I just copy/paste the same properties on both objects...

Thats a workaround but not solution for me. I use Typescript 2 and transpile to ES5.

What possibilities do I have with object.assign and different types for source/target to solve this problem?

AssignedPupil.ts

import { GradeScorePair } from './gradeScorePair';
export class AssignedPupil {

    constructor(obj: any) {
        this.id = obj.id;
        this.name = obj.firstName + " " + obj.lastName;
    }

    id: number;
    name: string;
    gradeScorePairs: GradeScorePair[];
    isSelected: boolean;
    selectedGradeScorePair: GradeScorePair;
}

UnAssignedPupil.ts

import { GradeScorePair } from './gradeScorePair';
export class UnAssignedPupil {

    constructor(obj: any) {
        this.id = obj.id;
        this.name = obj.firstName + " " + obj.lastName;
    }

    id: number;
    name: string;
    // gradeScorePairs: GradeScorePair[]; // don`t need it on the unassigned html table
    isSelected: boolean;
    // selectedGradeScorePair: GradeScorePair; // don`t nee it on the unassigned html table
}

  unassignPupil() {
    var i = this.assignedPupils.length;
    while (i--) {
      var p = this.assignedPupils[i];
      if (p.isSelected) {
        let assignedPupil: AssignedPupil = this.assignedPupils.splice(i, 1)[0];
        let unAssignedPupil: UnAssignedPupil = Object.assign({}, assignedPupil);
        unAssignedPupil.isSelected = false;
        this.unAssignedPupils.push(unAssignedPupil);
      }
    }
  }

  assignPupil() {
    var i = this.unAssignedPupils.length;
    while (i--) {
      var p = this.unAssignedPupils[i];
      if (p.isSelected) {
        let pupilToAssign: UnAssignedPupil = this.unAssignedPupils.splice(i, 1)[0];
        let assignedPupil: AssignedPupil = Object.assign({}, pupilToAssign);

        // Difference are these 2 lines of code
        assignedPupil.gradeScorePairs = this.gradeScorePairs;
        assignedPupil.selectedGradeScorePair = null;

        assignedPupil.isSelected = false;
        this.assignedPupils.push(assignedPupil);
      }
    }
  }

1 Answer 1

2

You can tell the compiler that this empty object is of type AssignedPupil:

let assignedPupil: AssignedPupil = Object.assign({} as AssignedPupil, pupilToAssign);

That will clear the error.

The thing is, that when doing that you won't really have an instance of class AssignedPupil, you'll have an object with the same properties.
You won't have errors because of the duck typing nature of typescript.

If you intend to use that class as a data object only then you're fine (but why not just using interfaces?), but if you plan to have class methods then the variable assignedPupil won't have those.


Edit

An example:

class Point {
    constructor(public x: number, public y: number) { }

    distance(other: Point) {
        return Math.sqrt(Math.pow((this.x - other.x), 2) + Math.pow((this.y - other.y), 2));
    }

    toString() {
        return `(${this.x}, ${this.y})`;
    }
}

let a1 = new Point(0, 0);
console.log(a1.x); // 0
console.log(a1); // Point {x: 0, y: 0}
console.log(a1.toString()); // (0, 0)

let a2 = Object.assign({} as Point, a1);
console.log(a2.x); // 0
console.log(a2); // Object {x: 0, y: 0}
console.log(a2.toString()); // [object Object]

console.log(a1.distance(a2)); // 0
console.log(a2.distance(a1)); // Uncaught TypeError: a2.distance is not a function

(code in playground)

Sign up to request clarification or add additional context in comments.

4 Comments

Both pupil objects are just data objects for now.
So cast it to AssignedPupil and the error goes away. But if that's the case, then there's no need for classes, use interfaces.
I am coming from C# being TS newbie. BUT interfaces can`t be instantiated and I am still creating those UnAssignedPupils/AssignedPupils from server data their I have to new up both object types from json.
You only initiate part of the objects. You can do: Object.assign(new AssignedPupil(), pupilToAssign) which will instantiate a new AssignedPupil and then assign the values, but you'll need to deal with an empty constructor.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.