简体   繁体   中英

TypeError: “name” is read-only

I am trying to implement the prototype pattern in a Sharepoint Framework small example, I took the sample from here:

https://mertarauh.com/tutorials/typescript-design-patterns/prototype-pattern/

and adapted as below:

 class Employee  {

    private totalperMonth: number;


    constructor(public name: string, public hiredDate: Date, public dailyRate: number){
        this.totalperMonth = dailyRate * 20 ;
    }

    public display(): string{
        return "Employee " + this.name + " earns per month: " + this.totalperMonth;
    }

    public clone():Employee{
        var cloned = Object.create(Employee || null);
        Object.keys(this).map((key: string) => {
            cloned[key]= this[key];
        });
        return <Employee>cloned;
    }
}

export default Employee;

and the component

import * as React from 'react';
import styles from './Prototype.module.scss';
import { IPrototypeProps } from './IPrototypeProps';
import { escape } from '@microsoft/sp-lodash-subset';
import  Employee from './Employee';


export default class Prototype extends React.Component<IPrototypeProps, {}> {


  public render(): React.ReactElement<IPrototypeProps> {
    const today = new Date();
    let employee1: Employee = new Employee('Luis', today, 500);
    let employee2 = employee1.clone();
    employee2.dailyRate = 550;

    return (
      <div className={ styles.prototype }>
        <div className={ styles.container }>
          <div className={ styles.row }>
            <div className={ styles.column }>
              <span className={ styles.title }>Welcome to SharePoint!</span>
              <p className={ styles.subTitle }>Customize SharePoint experiences using Web Parts.</p>
              <p className={ styles.description }>{escape(this.props.description)}</p>
                <span className={ styles.label }>{employee1.display()}</span>
                <span className={ styles.label }>{employee2.display()}</span>
            </div>
          </div>
        </div>
      </div>
    );
  }
}

However I get in the console this error:

What am I missing?

在此处输入图片说明

There are several problems with this approach.

Classes are first-class citizens in TypeScript, alternative approaches to inheritance can make type safety much less straightforward.

Object.create is low-level tool, it isn't a good idea to use it unless you know what you're doing and why. The actual mistake here is that wrong prototype was chosen ( Employee instead of Employee.prototype ), so name property refers to function name property , which is read-only and shouldn't be reassigned. A proper way to implement clone would be:

public clone():Employee{
    return Object.assign(Object.create(Employee.prototype), this);
}

The fact that it ignores class constructor is a doubtful decision because a constructor may contain logic that differs from one applied in clone .

React promotes functional programming as a substitute to OOP, it's beneficial to maintain application state as plain objects rather than class instances, this may help to avoid design flaws that will be costly to fix in future. There's nothing that would really require a class in this case. The same thing could be expressed as:

const createEmployee = (name, hiredDate, dailyRate) => ({
 name,
 hiredDate,
 dailyRate,
 totalperMonth: dailyRate * 20
});

...

let employee1 = createEmployee('Luis', today, 500);
let employee2 = {...employee1, dailyRate: 550};

Notice that totalperMonth isn't recalculated neither in Employee class nor in createEmployee factory function. This may be undesirable (see the note on a constructor above).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM