object.assign не работает с разными типами с помощью typescript

#typescript #typescript2.0

#typescript #typescript2.0

Вопрос:

Только представьте, что у меня есть 2 HTML-таблицы рядом друг с другом. Каждая таблица содержит массив неназначенных учеников или назначенных учеников для определенного теста. С помощью 2 кнопок вы можете переместить эти выбранные флажком ученики в другую таблицу html.

Ученики в обеих таблицах html имеют почти одинаковые свойства.

Когда я использую Object.Назначьте, затем я получаю ошибку компиляции:

 properties gradeScorePairs is missing in type {} and UnAssignedPupil
  

Чтобы исправить эту ошибку, я просто копирую / вставляю одни и те же свойства для обоих объектов…

Это обходной путь, но не решение для меня. Я использую Typescript 2 и переношу в ES5.

Какие возможности у меня есть с object.assign и различными типами для источника / цели для решения этой проблемы?

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:

Вы можете сообщить компилятору, что этот пустой объект имеет тип AssignedPupil :

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

Это устранит ошибку.

Дело в том, что при этом у вас на самом деле не будет экземпляра class AssignedPupil , у вас будет объект с теми же свойствами.
У вас не будет ошибок из-за того, что typescript использует типизацию с уткой.

Если вы собираетесь использовать этот класс только как объект данных, тогда все в порядке (но почему бы просто не использовать интерфейсы?), Но если вы планируете использовать методы класса, тогда переменная assignedPupil не будет иметь их.


Редактировать

Пример:

 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
  

(код на игровой площадке)

Комментарии:

1. Оба объекта pupil на данный момент являются просто объектами данных.

2. Поэтому приведите его к AssignedPupil , и ошибка исчезнет. Но если это так, то нет необходимости в классах, используйте интерфейсы.

3. Я пришел из C #, будучи новичком. НО интерфейсы не могут быть созданы, и я все еще создаю эти неназначенные / назначенные объекты из данных сервера, поэтому мне нужно создать оба типа объектов из json.

4. Вы инициируете только часть объектов. Вы можете сделать: Object.assign(new AssignedPupil(), pupilToAssign) который создаст экземпляр new AssignedPupil , а затем присвоит значения, но вам нужно будет иметь дело с пустым конструктором.