2

In Kotlin a data class can be copied using its auto-generated copy function.

val jack = User(name = "Jack", age = 1)
val olderJack = jack.copy(age = 2)

The copy function signature, as per documentation (Docs):

fun copy(name: String = this.name, age: Int = this.age) = User(name, age)

Can something like this be done in TypeScript?
Is this an acceptable solution, or can it be improved somehow?

export class User {
    constructor(
            public name: string,
            public age: number) {}

    copy(parameters: {
        name?: string,
        age?: number
    }): User {
        const { name, age } = parameters
        return new User(name || this.name, age || this.age)
    }
}

This could be solved even with a Partial<User>:

copy(partialUser: Partial<User>): User {
   return new User(
            partialUser.name || this.name,
            partialUser.age || this.age)
}

1 Answer 1

4

You can deconstruct the item as shown below:

class User {
    constructor(
            public name: string,
            public age: number) {}
}

const jack = new User("Jack", 1);

const newJack = { ...jack, age: 2 };

This results in the copy, except the age, which is now 2.

The ordering is important (i.e. age must follow the object deconstruction).

Extended example below:

class User {
    constructor(
        public name: string,
        public age: number) { }

    copy(user: Pick<User, 'name' | 'age'>) {
        return new User(user.name, user.age);
    }
}

const jack = new User("Jack", 1);

const newJack = jack.copy({ ...jack, age: 2 });

console.log(newJack);
Sign up to request clarification or add additional context in comments.

7 Comments

Wouldn't I lose eventual instance / static functions?
I have added a wider example where newJack is the full User.
Thanks! Do you find Pick more appropriate then Partial?
With Pick you say "it must have the members I state", wheras Partial says "I don't know what it's going to have". In our case, we can be quite strict that we expect name and age to be supplied and we don't care about copy. So the following will be caught as an error in our Pick example: const newJack = jack.copy({ age: 2 });
Interesting! I could even just use (user: Pick<User>): User { ... } then. Do you think that my Partial example was not appropriate? I ask so I'm able to understand if I'm doing right or wrong in general terms
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.