iwetish
iwetish

Reputation: 26

constructor function and new object in javascript / typescript

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

Answers (2)

Joseph M
Joseph M

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

jcalz
jcalz

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.

Playground link to code

Upvotes: 3

Related Questions