Creating Instances of a Subclass from an Object in TypeScript

Here is the code snippet I am working with:

class MyClass {
    name: string = "myname";
    constructor(public action: string) { }
}

let obj1: MyClass = { action: "act1" };

The code does not compile and the error displayed pertains to the last line:

Property 'name' is missing in type '{ action: string; }' but required in type 'MyClass'.

I had expected that since the 'name' property has a default value, it would not be necessary to specify it for obj1. However, this was not the case. Furthermore, it appears that the last line does not trigger the constructor, suggesting it is not simply syntactic sugar for the constructor call. Is there a way to set defaults for certain properties and avoid initializing them using this method?

Answer №1

Consider the following scenario:

let obj1: MyClass = { action: "act1" };

In this case, you are utilizing the class MyClass as a type. This means that you are informing the compiler that the variable obj1 adheres to the MyClass type. It must have all the required fields of the class and cannot include any unknown properties.

This approach is beneficial because if the type consists of numerous properties, the intellisense can warn you about any missing properties.

However, it's important to note that MyClass is not just a type or interface; it also serves as a class. Therefore, it offers functionality such as constructor invocation and the ability to utilize extends when defining the class.

Default properties in a class do not automatically become default properties for the type. While attempting to add an initializer in a TypeScript interface or type will generate an error, assigning a default property in a class ensures that an instance will have that property initialized with the default value only during construction.

There are several ways to address this issue:

  1. You can continue using MyClass as a type in this situation, but make sure to declare the name property in the object literal as well:

let obj1: MyClass = {action: "act1", name: "first"};

Even after doing this, you may encounter:

Object literal may only specify known properties

This occurs because the action property does not exist in MyClass. You would need to add an action property to MyClass.

  1. Use a constructor

let obj1 = new MyClass("act1");

If possible, it is recommended to call the class constructor instead of solely using classes as types/interfaces, as shown in this example. Alternatively, consider utilizing an interface, as suggested in a comment.

In this particular scenario, invoking the constructor seems like the preferable choice.

  1. If your main objective is to leverage compiler checks/intellisense on the variable type, consider using an interface:
interface MyCustomType {
  name: string;
  action?: string;
}

This way, you will receive a warning if you attempt to assign a variable as MyCustomType without specifying the name:

let obj: MyCustomType = {
  action: 'act1',
} // error, 'name' needs to be set as it is a required field

You can choose to include or exclude the action property since it is optional (denoted by '?').

However, adding unknown fields will result in an error:

let obj: MyCustomType = {
  name: 'name',
  value: 1, // error, unknown field
}

Answer №2

When writing your code, make sure to properly initialize instances of classes like this:

If you want to create an instance of MyClass, do it like this:

let obj1 = new MyClass("action");

By doing so, you avoid TypeScript errors and ensure that the type of variable matches the class definition.

Here is how the correct implementation looks like:

class MyClass {
    name: string = "myname";
    constructor(public action: string) { 
    }
}

let obj1 = new MyClass("action");
console.log(obj1);

/* 
   outputs:

   {
      action: "action"
      name: "myname"
   }
*/

Answer №3

After considering the suggestions provided earlier, I have successfully devised a solution that allows me to utilize the constructor while ensuring any missing or extra values result in errors and also enables me to set default values in the object literal "initializer":

class MyClassValues {
    constructor(public name: string, public action?: string) {}
}

class MyClass extends MyClassValues {
    constructor(v: MyClassValues) {
        super(v.name, "default1");
    }
}

let c1 : MyClass = new MyClass({}); // error, missing name
let c2 : MyClass = new MyClass({x:"y"}); // error, unknown prop
let c3 : MyClass = new MyClass({name:"hello"}); // no error
console.log(c3.action); // prints "default1";

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

Exploring the chosen choice in the Material Design Lite select box

Consider the following scenario. If I want to extract the name of the country chosen using JavaScript, how can this be achieved? <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label getmdl-select getmdl-select__fullwidth"> ...

Controlling the Flow of Events in JavaScript Documents

Explore the integration of two interconnected Javascript files and delve into managing event propagation between them effectively. 1st js file var red = [0, 100, 63]; var orange = [40, 100, 60]; var green = [75, 100, 40]; var blue = [196, 77, 55]; var ...

Using Javascript to dynamically add rows to a table, however they mysteriously appear and disappear soon

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="UserPermisson.aspx.cs" Inherits="TestProjects.UserPermisson" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" ...

Service in Angular JS dispatching coordinates to controller

I am in need of retrieving a path consisting of latitude and longitudes for displaying on a map within my app. To handle all the API calls, I have set up a basic controller. function mainController($scope, $http){ $http.get('/api/lastrun') ...

Having trouble updating the value in the toolbar?

Here is an example that I added below: When I click the add button, the value of the "newarray" variable is updated but not reflected. I am unsure how to resolve this issue. This function is used to add new objects: export class AppComponent { ne ...

Issue with ng-show directive in AngularJS

Currently, I am developing a web app using AngularJS 1.6.6. In my template, I have implemented ng-show in order to recycle it: <div > <br/> <div class="form"> <form data-ng-submit="objectHandlerVM.functions.objectHandl ...

Pointer Permissions parsing does not permit creation

Despite meticulously following the instructions in this guide, I am encountering a 403 error when attempting to create a new row: Error code: 119 Error message: "This user does not have permission to carry out the create operation on Messages. This s ...

JavaScript: Generating Images from Text

Currently, I am working on a fun project that involves converting a string of text into GitHub commits. The final result is expected to resemble this: https://i.sstatic.net/2qKEi.png To achieve this, I am developing a solution where each character in the ...

The Twitch stream is currently live, but the user is not actively online

I've developed a NODE JS bot that keeps track of Twitch users and sends a message to the "GroupMe" app whenever a user goes online. Although it generally works well, there are instances when the bot mistakenly indicates that a user is online when they ...

Combining two ng-model inputs in Angular for seamless data integration

New to Angular and seeking some guidance. I currently have two input fields, one for the area code and the other for the number. // Input field for area code <input area-input type="tel" required="true" name="area" ng-model="employee.home.area">&l ...

Fixing a CSS animation glitch when using JavaScript

I'm facing an unusual issue with my CSS/HTML Check out my code below: a:hover { color: deeppink; transition: all 0.2s ease-out } .logo { height: 300px; margin-top: -100px; transition: all 0.2s ease-in; transform: scale(1) } .logo:hover { transit ...

From jQuery to ReactJS: Migrating to a Modern

As I venture into converting existing jQuery code to React.js, I must admit that I am quite new to React and still in the learning phase. So please bear with me if my questions sound a bit silly. Here is the structure I am working with: <ul> &l ...

How to modify the color of a div element with jQuery?

I need some help changing the color of a div with 'jQuery', but I am not sure how to do it. Below is the code I have been trying: function updateDivColor() { $('#OutlineX1').css("color","blue"); } ...

Retrieve only the final number within the sequence using JavaScript

I am receiving a series of numbers from an API. Here is how they look: 1,2,3,4,5,6 My goal is to only display the last digit instead of all of them. How can I achieve this? I know that I need to add .slice at the end, but I'm unsure about what to p ...

Retrieve the prior position using the AngularJS ui-router

Utilizing fromState and fromParams within the $stateChangeSuccess event allows us to access all details regarding the previous location. This concept is elaborated in the following discussion: Angular - ui-router get previous state $rootScope.$on('$s ...

Clarification: Javascript to Toggle Visibility of Divs

There was a similar question that partially solved my issue, but I'm wondering if using class or id NAMES instead of ul li - such as .menu, #menu, etc. would work in this scenario. CSS: div { display:none; background:red; width:200px; height:200px; } ...

Extracting dynamic content from a webpage using Selenium with Javascript rendering capabilities

Seeking a way to extract data that populates the SVG elements on a specific page: The page seems to be driven by JavaScript, making traditional BeautifulSoup methods in Python ineffective. After inspecting the network for XHR requests, it doesn't see ...

Prevent any screen interactions by disabling clicks, and then re-enable them either after a set amount of

My app uses PhoneGap and jQuery Mobile. The issue I am facing is that when I navigate from page A to page B with a single click, everything works fine. However, if I accidentally double-click on page A and move to the next screen (page B) before it's ...

Accessing the Next.js API after a hash symbol in the request URL

Is there a way to extract query strings from a GET request URL that contains the parameters after a '#' symbol (which is out of my control)? For example: http://...onnect/endpoint/#var_name=var_value... Even though request.url does not display a ...

Issue: Utilized more hooks than in the previous render cycle

After the initial load of a component that renders and makes data calls on the client side, everything works fine. However, when clicking a "see more" button to make another call, an error occurs in the console indicating that there are too many hooks be ...