I have a pretty simple code.
There is a model with toString overwritten:
policy.ts:
export class Policy {
public id: number;
public name: string;
public description: string;
toString(): string {
return this.name + ': ' + this.description;
}
}
Then I use the Policy model in two ways.
binding to create-policy.component.html:
...
<input type="text" name="name" [(ngModel)]="policy.name" required>
and it in the component create-policy.component.ts:
import { Component, OnInit } from '@angular/core';
import { Policy } from '../models/policy';
@Component({
selector: 'app-create-policy',
templateUrl: './create-policy.component.html',
styleUrls: ['./create-policy.component.css'],
})
export class CreatePolicyComponent implements OnInit {
policy: Policy = {
id: 0,
name: '',
description: '',
};
constructor() {}
ngOnInit() {}
onSubmitPostHttp() {
console.log('Started onSubmitPostHttp');
console.log('policy=' + this.policy.toString());
}
}
Still on the console I do not get properties; it prints:
create-policy.component.ts:23 policy=[object Object]
Direct logging properties works properly:
console.log("policy=" + this.policy.name);
That prints:
policy=ss
policy isn't an instance of Policy and still uses native toString method.
The fact that Policy class is used as interface like policy: Policy doesn't instantiate it. Since plain object conforms to this interface (it already has toString method), this doesn't cause type error.
It can be:
policy = Object.assign(new Policy, {
id: 0,
name: "",
description: ""
});
At this point it becomes obvious that Policy class wasn't designed for what it's used, it's better to move property initialization to its constructor:
export class Policy {
constructor(
public id: number,
public name: string,
public description: string
) {}
toString(): string {
return this.name + ': ' + this.description;
}
}
and
policy = new Policy(
id: 0,
name: "",
description: ""
);
You are creating this.policy as a new object without overriding the toString() method. And that is why it still uses the default implementation when logging the result.
Look at the generated javascript code when creating a typescript class:
TS Code:
export class Policy {
public id: number;
public name: string;
public description: string;
toString(): string {
return this.name + ': ' + this.description;
}
}
let pol: Policy = {
id: 0,
name: "",
description: ""
};
JS Code:
define(["require", "exports"], function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var Policy = /** @class */ (function () {
function Policy() {
}
Policy.prototype.toString = function () {
return this.name + ': ' + this.description;
};
return Policy;
}());
exports.Policy = Policy;
var pol = {
id: 0,
name: "",
description: ""
};
});
As you can see here, the toString() method is added to the prototype of the Policy object. There are alot you can read about prototypes in javascript but the key thing here is that the prototype for the policy does not get called unless you use the new operator.
As estus mentioned; all objects in javascript has a toString method, it is included in the object prototype. That is the reason why you are not getting any errors when creating your object directly, it has all the correct properties and methods for a policy object and that is why typescript allow this behaviour.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With