Why is it necessary to define a property outside the constructor in Typescript, when in Javascript I wouldn't have to do that?

When working with Javascript, creating a class like the one below allows us to avoid declaring and initializing a property named logs outside of the constructor:

class Logger {
  constructor() {
    this.logs = [];
  }
}

However, transitioning to TypeScript presents an error message:

Property 'logs' does not exist on type 'Logger'.ts(2339)
To resolve this issue, we can declare the property logs in the following manner: logs: Array<any>; A corrected TypeScript pseudo code snippet would appear as follows:

class Logger {
  logs: Array<any>;

  constructor() {
    this.logs = [];
  }
}

This question may be common for beginners exploring TypeScript. While the solution is clear, understanding the nuances, differences, and best practices between JavaScript and TypeScript remains crucial.

Answer №1

Understanding the reasoning behind the need for a type definition can be quite complex. This question can be broken down into two main components.

1. Why is a type definition necessary?

VLAZ highlighted in their comment that TypeScript often requires more explicit guidance because it may not have enough information to infer the correct type on its own.

While some may argue that TypeScript should be able to deduce that an object is an array by default, there are situations where this isn't as straightforward.

2. Why must the type definition be specified at the beginning of the class?

The presence of constructors can add complexity to determining variable types. Consider a different scenario with the following class:

class Logger { 
  a() {
    this.logs = 1234;
  }

  b() {
    this.logs = ['a', 'b']
  }
}

In this example, the type of `logs` could vary depending on whether `a()` or `b()` is called first. To avoid ambiguous situations like this, TypeScript enforces declaring types at the top of the class, outside of any method.

You might wonder why TypeScript doesn't infer types from the constructor alone, which always precedes other methods. One possible explanation is related to the ability to set fields during declaration, leading to unexpected outcomes.

class Logger {
  logs: Array<string> = ['a', 'b'];
  
  constructor() {
    this.logs = 6611; // <-- potential confusion
  }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The utilization of ES Modules within a Next.js server.js

After reviewing a few examples in the Next.js repository, I came across: https://github.com/zeit/next.js/tree/master/examples/custom-server-express https://github.com/zeit/next.js/tree/master/examples/custom-server-koa I observed that these examples ut ...

Tips for aligning text in MUI Breadcrumbs

I am currently utilizing MUI Breadcrumb within my code and I am seeking a solution to center the content within the Breadcrumb. Below is the code snippet that I have attempted: https://i.stack.imgur.com/7zb1H.png <BreadcrumbStyle style={{marginTop:30}} ...

React Hook is failing to trigger an update

Learning React and JavaScript has been quite a challenge for me, especially when it comes to understanding React Hooks and the issue of them not updating sometimes. I have tried searching online but either end up with solutions for class-based components o ...

Need to import a JSON file and convert it to an interface in order to ensure that all fields are included

I am facing an issue where I am attempting to parse a json file using require(). My goal is to convert it into a specific data type and have the conversion fail if the file does not contain all the necessary fields as defined by the interface. Below is my ...

Encountered an issue with trying to access the 'map' property of an undefined value while using Express and VueJS

Currently, I am in the process of developing a fullstack application utilizing Express, VueJS, and Mongoose. The app functions as a news feed platform. A couple of days ago, I encountered an error which was resolved with the help of your guidance. However, ...

Should objects passed as props be modified in Vue.js components?

I've observed that in Vue, object fields passed as Props can be changed, and these changes reflect in the parent component. Is this considered a bad practice? Should it be avoided, or is it acceptable to use? What are the potential pitfalls of this a ...

When running collection.find().toArray(callback) in node.js with mongodb, the result is coming back

When I run my code, mydocuments.find({}).toArray is returning empty. I have seen some solutions posted but they don't apply to my situation since I am using MongoClient.connect. Any help would be greatly appreciated. var MONGOHQ_URL="mongodb://harish ...

Deactivate a span in real-time using ng-model

I found a helpful guide on creating a custom editable <span> using ngModelController here: https://docs.angularjs.org/api/ng/type/ngModel.NgModelController#example Now, I am looking to implement a feature that allows me to dynamically disable editin ...

Encountering a problem when verifying if the data is in JSON format using JavaScript

I'm using JavaScript to determine whether an input value is in JSON format, but I've encountered a problem with a specific value. Below is my code explanation. isJSON = async(str) => { try { return (JSON.parse(str) && !!str); ...

Incorporating a JavaScript file into Angular

I'm looking to incorporate a new feature from this library on GitHub into my Angular project, which will enhance my ChartJS graph. @ViewChild('myChart') myChart: ElementRef; myChartBis: Chart; .... .... const ctx = this.myChart.nativeEleme ...

When $this is called outside of object context

I am currently in the process of developing a function to display blogs. However, I have encountered an issue with my show blog function where it is generating an error stating "Using $this when not in object context." Class Blog{ public function g ...

Encountering TypeScript error 2345 when attempting to redefine a method on an Object Property

This question is related to Object Property method and having good inference of the function in TypeScript Fortunately, the code provided by @jcalz is working fine; const P = <T,>(x: T) => ({ "foo": <U,>(R: (x: T) => U) => ...

Exploring nested arrays in JSON through iteration

Here is the JavaScript code I am working on (the "data" variable is retrieved from a json call): if (data.projectReports.length) { for (var i in data.projectReports){ var report = data.projectReports[i]; $('#reports').append( & ...

Node.js meets Blockly for a dynamic programming experience

Can anyone help me figure out how to run blockly on Node.js and have the code execute directly on the server without having to save the XML first and then run it in the background? I've attempted to use various npm modules but haven't found one t ...

Manipulating an element in the JSON data is causing alterations to the preceding elements

I am facing a challenge with two JSON arrays. $scope.arr1 = [ { "id": 1, "first_name": "Philip", "last_name": "Kim", "email": "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="1e6e7577732e5e737b7a777f78776c7b307d717 ...

What are the different kinds of properties that can be used in Vue.js

When working with Javascript, I can create arrays that hold different types of data elements like: var ex = ['name', 12, true]; console.log(ex); In Vue JS, when defining props for a component within a single file template, I have the option to ...

Develop a Typescript interface containing all the necessary properties for a specific JSX component

My goal is to create a ControlledInputComponent that consists of a label and an input inside a div. I aim to make it highly customizable as I plan on using it in various ways. At the moment, I have included all the necessary elements, but I would like to e ...

Learn how to implement a vertical bar chart in Highcharts by using it as a component and passing it as props

I recently imported a Bar Chart component from Highcharts, but it is being displayed horizontally. I would like to convert it into a vertical chart instead. Can someone please assist me in achieving this by passing the necessary props? <template v-slot ...

``ScrollTop does not function properly in Safari when trying to reach the scroll

When implementing divRef.current.scrollTop = divRef.current.scrollHeight in my React project, I encountered an issue where it properly scrolled to the end in Chrome but not in Safari. divRef.current.scrollTop = divRef.current.scrollHeight ...

Is it possible to determine the location of the "phantom image" while moving an object?

Is there a method to retrieve the location of the ghost image when an element is dragged? This is how the scenario is set up: <div id="test" v-on:dragstart="dragStart" v-on:drag="dragging" draggable="true" v-on:drop="drop" v-on:dragover="allowDrop"> ...