1
class Todo {
    private _date: Date;
    public name: string;

    constructor(todo: Todo) {
        this._date = todo._date;
        this.name = todo.name;
    }

    get date() { ... }
}
// example
const todos = Agent.fetchTodos();

const modifiedTodos1 = map.todos(todo => new Todo(todo)); // works fine
const modifiedTodos2 = map.todos(todo => new Todo( { ...todo, _date: new Date() } )); // doesn't work

The second modifiedTodos2 line of code gives me the following error: property date is missing in type [...]

In my scenario, I'm required to use the spread operator to extend the todo object with an additional prop. But I'm not sure why I'm seeing this error and how to deal with it... and I also can't make the date optional with ? operator.

Thank you so much in advance for pointing out why my scenario doesn't work and what to do to make it work!

1
  • 1
    I think this declaration get date() { ... } is restricting the creation of additional properties or at least is setting the attr date as a required property. Commented Jan 31, 2020 at 9:46

2 Answers 2

2

What you are trying to do is wrong because you do not consider encapsulation. _date is a private field that should not be accessed outside of the object. You defined the getter date, use it.

You should not use

this._date = todo._date;

but

this._date = todo.date;.

Here is an example :

class Todo {
  private _date: Date;
  public name: string;

  constructor(todo) {
    this._date = todo.date;
    this.name = todo.name;
  }

  get date(): Date {
    return this._date;
  }
}

const todo = new Todo(null);

const modifiedTodos1 = new Todo(todo);

const modifiedTodos2 = new Todo({
  ...todo,
  date: new Date(),
});

Also note that it will not work if you strongly type todo in the constructor like:

  constructor(todo: Todo) {
    this._date = todo.date;
    this.name = todo.name;
  }

Because typescript is waiting for a Todo object that you do not provide using the spread operator (no date function).

To adress this issue I recommend you to specify an interface that will only contains your setters data.

interface ITodo {
  date: Date,
  name: string,
}

class Todo {
  private _date: Date;
  public name: string;

  constructor(todo: ITodo) {
    this._date = todo.date;
    this.name = todo.name;
  }

  get date(): Date {
    return this._date;
  }
}

const todo = new Todo(null);

const modifiedTodos1 = new Todo(todo);

const modifiedTodos2 = new Todo({
  ...todo,
  date: new Date(),
});
Sign up to request clarification or add additional context in comments.

Comments

1

In addition of previous answer. Except of interface, you can use types:

declare type TodoType ={
    name:string,
    date:Date
}
class Todo {
    private _date: Date;
    public name: string;

    constructor(todo: TodoType) {
        this._date = todo.date;
        this.name = todo.name;
    }

    otherBehavior = ()=> {}

    get date() { return this._date;}
}

const toDos:Array<Todo> = [];

const modifiedTodos2 = toDos.map(todo => new Todo( { ...todo, date: new Date() } )); 

This way you can add additional behavior(properties/methods) to your Todo class and there will not be need to pass these in the object which you pass to create instance of Todo

Comments

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.