Reputation: 26
I have a task to make a constructor function to make a Circle
object what calculates area and perimeter.
So far I got the code below and don't understand why this
is underlined and why new Circle(3)
is underlined.
I have tried to change function Circle(this:any, radius: number) {
to remove underlined this
but I don't understand why then underlined new Circle
doesn't fix.
function Circle(radius: number) {
const pi = 3.14;
this.radius = radius;
this.area = function () {
return pi * radius * radius
}
this.perimeter = function () {
return 2 * pi * radius;
}
}
// pi * r kv
//2pi*r
const c = new Circle(3);
console.log("Area =", c.area().toFixed(2)); // Expected output: Area = 28.27
console.log("Perimeter =", c.perimeter().toFixed(2)); // Expected output: Perimeter = 18.85
Upvotes: 0
Views: 1578
Reputation: 159
Hope I understand what you need.
You can use Class
instead of using a Function
.
Here is the simple solution which you wanted.
class Circle {
radius:number;
pi = 3.14;
constructor(radius:number) {
this.radius = radius;
}
area():number {
return this.pi * this.radius * this.radius;
}
perimeter():number {
return 2 * this.pi * this.radius;
}
}
var c = new Circle(3);
console.log('Area = '+c.area().toFixed(2));
console.log('Area = '+c.perimeter().toFixed(2));
It won't throw any error and follows every standard procedures. Good luck.
Upvotes: 0
Reputation: 329943
Assuming this is in a TypeScript file (and not a JavaScript file checked with TypeScript), then this is explicitly not supported, according to microsoft/TypeScript#2310. If you want a class constructor in TypeScript, it is strongly recommended that you use class
syntax. It will be downleveled to a function
if the --target
is ES5 or below, so you don't have to worry about that. If you use class
syntax, the this
context and new
will just work:
class Circle {
radius: number;
area: () => number;
perimeter: () => number;
constructor(radius: number) {
const pi = 3.14;
this.radius = radius;
this.area = function () {
return pi * radius * radius
}
this.perimeter = function () {
return 2 * pi * radius;
}
}
}
const c = new Circle(3); // okay
(Normally I'd expect methods to be on the prototype and not on the instance, but I mostly left your implementation alone).
If you really need to support functions as constructors in TypeScript, you'll have to use type assertions to tell the compiler that you know what you're doing:
interface Circle {
radius: number;
area: () => number;
perimeter: () => number;
}
interface CircleConstructor {
new(radius: number): Circle;
}
const Circle = function Circle(this: Circle, radius: number) {
const pi = 3.14;
this.radius = radius;
this.area = function () {
return pi * radius * radius
}
this.perimeter = function () {
return 2 * pi * radius;
}
} as any as CircleConstructor;
const c = new Circle(3); // okay
In the above I've explicitly defined interfaces for both the Circle
instance type and the CircleConstructor
constructor type: these happen automatically for you if you use class
syntax, where the types would be named Circle
and typeof Circle
respectively. Then the Circle
function needs to be asserted to be of the type CircleConstructor
in order for the new Circle(3)
call to work. Additionally, I gave the function signature a this
parameter, which doesn't exist at runtime but serves to tell the compiler what type it should consider this
inside the implementation. I said this: Circle
to let the compiler know that inside the Circle
function, it could access this
properties as if this
is a Circle
instance.
So this works more or less the same as the class
version, except you have to jump through unnecessary hoops to do it, and it's less type safe to boot. So unless you're doing this for some kind of magic trick (watch me get out of this sealed crate using only a toothpick) I'd strongly recommend that you use class
syntax, and push back on anyone who asks you to do otherwise in TypeScript.
Upvotes: 3