TypeScript override ToString()

JavascriptTypescriptOverridingTostring

Javascript Problem Overview


Let's say I have a class Person which looks like this:

class Person {
    constructor(
        public firstName: string,
        public lastName: string,
        public age: number
    ) {}
}

I have overridden the toString method as follows.

public toString(): string {
    return this.firstName + ' ' + this.lastName;
}

Now I expect to be able to do the following, which works in runtime:

function alertMessage(message: string) {
    alert(message);
}

alertMessage(new Person('John', 'Smith', 20));

But this still gives me this error:

> TS2345: Argument of type 'Person' is not assignable to parameter of type 'string'.

How can I assign a Person to this string argument?

Javascript Solutions


Solution 1 - Javascript

Overriding toString works kind of as expected:

class Foo {
    private id: number = 23423;
    public toString = () : string => {
        return `Foo (id: ${this.id})`;
    }
}

class Bar extends Foo {
   private name:string = "Some name"; 
   public toString = () : string => {
        return `Bar (${this.name})`;
    }
}

let a: Foo = new Foo();
// Calling log like this will not automatically invoke toString
console.log(a); // outputs: Foo { id: 23423, toString: [Function] }

// To string will be called when concatenating strings
console.log("" + a); // outputs: Foo (id: 23423)
console.log(`${a}`); // outputs: Foo (id: 23423)

// and for overridden toString in subclass..
let b: Bar = new Bar();
console.log(b); // outputs: Bar { id: 23423, toString: [Function], name: 'Some name' }
console.log("" + b); // outputs: Bar (Some name)
console.log(`${b}`); // outputs: Bar (Some name)

// This also works as expected; toString is run on Bar instance. 
let c: Foo = new Bar();
console.log(c); // outputs: Bar { id: 23423, toString: [Function], name: 'Some name' }
console.log("" + c); // outputs: Bar (Some name)
console.log(`${c}`); // outputs: Bar (Some name)

What can sometimes be an issue though is that it is not possible to access the toString of a parent class:

console.log("" + (new Bar() as Foo));

Will run the toString on Bar, not on Foo.

Solution 2 - Javascript

As pointed out by @Kruga, the example actually seemed to work in runtime JavaScript. The only problem with this is that TypeScript shows a type error.

> TS2345: Argument of type 'Person' is not assignable to parameter of type 'string'.

To resolve this message, you must either:

  • Call .toString() explicitly
  • Or concatenate the object with a string (e.g. `${obj}` or obj + '')
  • Or use obj as any (not recommended as you will lose type safety)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDuncan LukkenaerView Question on Stackoverflow
Solution 1 - JavascriptNypanView Answer on Stackoverflow
Solution 2 - JavascriptDuncan LukkenaerView Answer on Stackoverflow