Defining preset values within a TypeScript model class

Suppose I have a User class and I want to instantiate only predefined 'status'. Is this the optimal approach? Are there any other alternatives? What is the correct way to achieve this? Thank you in advance.

export class User {
    constructor(
        username: string,
        email: string,
        status: AccountStatus
    ){}
}

export enum AcountStatus {
    Active = 'Active',
    Suspended = 'Suspended'
}

import { User } from 'app/models/user.model'
import { AccountStatus } from 'app/models/user.model'

private user: User;

this.user = new User('username', '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f580869087b580869087db9698">[email protected]</a>', AccountStatus.Active) 

Answer №1

If the majority of users are expected to have an initial status of Active, you can set a default value for the status in the constructor like this:

class User {
  constructor(
    public username: string,
    public email: string,
    public status: AccountStatus = AccountStatus.Active
  ){}
}

This way, when creating a new Active user, you don't have to specify the status each time:

let user: User;

user = new User('username', '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="dfaaacbaad9faaacbaadf1bcb2">[email protected]</a>')

Try it out on the playground.


Another approach you can take for improvement is to use a union type instead of the AccountStatus enum:

class User {
    constructor(
      public username: string,
      public email: string,
      public status: 'Active' | 'Suspended' = 'Active'
    ){}
}

let user = new User('username', '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="a1d4d2c4d3e1d4d2c4d38fc2cc">[email protected]</a>') 

Answer №2

If you're looking to provide more flexibility to the user of your code, you have the option to accept either a union of string literals or a member from your string enum:

TS Playground

type Values<T> = T[keyof T];
type StringEnumToUnion<T extends Record<string, string>> = `${Values<T>}`;

function valueIsStringEnum <Enum extends Record<string, string>>(
  value: unknown,
  o: Enum,
): value is Values<Enum> {
  return Object.values(o).includes(value as string);
}

function assert (expr: unknown, msg?: string): asserts expr {
  if (!expr) throw new Error(msg);
}

export enum AccountStatus {
  Active = 'Active',
  Suspended = 'Suspended',
}

export class User {
  constructor (
    username: string,
    email: string,
    status: StringEnumToUnion<typeof AccountStatus>,
  ) {
    let ac: AccountStatus;

    ac = status; /*
    ~~
    Type '"Active" | "Suspended"' is not assignable to type 'AccountStatus'.
      Type '"Active"' is not assignable to type 'AccountStatus'.(2322) */

    // Assert it back to AccountStatus for your own usage if you want:
    assert(valueIsStringEnum(status, AccountStatus));
    ac = status; // ok
  }
}


// Example usage:

new User('user', '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="dca9afb9ae9cb2bdb1b9f2a8b0b8">[email protected]</a>', 'ACTUVE'); /*
                                  ~~~~~~~~
Argument of type '"ACTUVE"' is not assignable to parameter of type '"Active" | "Suspended"'.(2345) */

new User('user', '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="cbbeb8aeb98ba5aaa6aee5bfa7af">[email protected]</a>', 'Active'); // ok
new User('user', '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="582d2b3d2a183639353d762c34

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

Is there a standardized method for obtaining a date in the format of six digits as YYMMDD?

In my current project, I'm developing a function that generates a list of dates represented in a 6-digit format beginning from the present day up until August of 2018. The desired output should resemble the following: [190322, 190321, 190320, ...] I ...

Adjusting slidesPerView based on screen size in Ionic: A step-by-step guide

Recently, I encountered an interesting challenge while working on my ionic project. I had successfully created a slider using ion-slides to display multiple products. Everything was working perfectly for the portrait view with 1.25 slides per view (slide ...

Select the text inside the current cell of a jqGrid table

The issue at hand is that when using jqGrid with cellEdit:true, users are unable to select text in a cell. Once the mouse button is released, the selection resets. This limitation prevents users from copying the selected text within cells. Has anyone enco ...

The 'clientX' property is not recognized on the 'Event' type in Angular2 Directive

When attempting to retrieve the X position of my mouse in an Angular2 Directive using the following code: @HostListener('mousemove', ['$event']) onMousemove(event: Event): void { console.log(event.clientX) } I encountered an error ...

Steps for eliminating an item from an array in MongoDB

I have been struggling with the functionality of the Mongoose library, specifically the remove method. On my webpage, I display comments and have a form with a Delete button. My objective is to delete only the comment that was clicked. Below is an excerpt ...

Patience is key when using Selenium with Node.js - make sure to wait for the

Is there a way to ensure my code waits until the page is fully loaded in Node.js while using selenium-webdriver version 4.0.0? const driver = new Builder().forBrowser("firefox").build(); await driver.get("http://www.tsetmc.com/Loader.a ...

What is the best way to reduce the size of TypeScript source code in an Electron application with the help of Electron Forge and Electron Packager

resolved: I was able to solve this issue using electron-builder, which utilizes webpack in the background to handle all problems efficiently. Initially, I faced this challenge while using electron-forge and electron-packager. Despite researching extensivel ...

The absence of a 'defaultValue' argument in Typescript React is causing an issue

I'm encountering an issue with my code. The error message states "An argument for 'defaultValue' was not provided." I am trying to set default values but unsure of what those values should be. Additionally, I am facing a couple of other err ...

Trouble with Metro UI Library: CSS not loading properly

I am having trouble with the navbar CSS on my website while using the Metro UI CSS library. Check out my HTML code: <!DOCTYPE html> <html lang="en"> <head> <title>TelePrint Blog</title> <link rel="stylesheet" href= ...

The code is functioning properly in the output, but it does not seem to be

I have been utilizing jquery chosen to implement a specific functionality, which is successfully demonstrated in the image below within the snippet. However, upon uploading the same code to my blog on Blogger, the functionality is not working as expected. ...

exploring the ins and outs of creating computed properties in TypeScript

How can I store an object with a dynamically assigned property name in an array, but unsure of how to define the array properly? class Driver { public id: string; public name: string; constructor(id , name) { this.id = id; th ...

The message states that the variable "Chart" has not been defined

I have been attempting to integrate ChartJS with Angular2, but I keep encountering an error message stating that 'Chart is not defined'. I made sure to install the ChartJS typings and referenced them accordingly. Additionally, I included the char ...

Why is AJAX returning false and I'm unable to figure out the reason?

My goal is to perform a database query for a keyword instantly upon input change. Currently, I am able to successfully execute the query and store all the results. However, when attempting to display the results using GET, my ajax function returns false. W ...

Executing a REST call only when the previous one has successfully completed

Is there a way to execute a second REST request only after multiple successful responses from the first one? I have noticed that while in a normal state these requests are executed sequentially as required, issues arise when dealing with a large number o ...

Karma Unit test: Issue with accessing the 'length' property of an undefined value has been encountered

While running karma unit tests, I encountered a similar issue and here is what I found: One of my unit tests was writing data to a json file, resulting in the following error: ERROR in TypeError: Cannot read property 'length' of undefined a ...

Scrolling through four limited list items automatically

Hey there! I am currently working on a design project. You can check it out here. I'm trying to replicate a section from another site, which you can see here. <div class="latest-winners-container"> <h3 class="header">Latest Winners< ...

Assigning a value to an attribute as either a "string" or null within JSON Schema while specifying a maximum length

I'm currently working on crafting a JSON schema that supports a nullable attribute. I am aiming to have the ability for specific JSON structures like this one be considered valid: { "some_name" : null } This is how my schema looks like: { "type" ...

Restrict input to only text characters in a textbox using AngularJS

Looking for a way to ensure that users can only input characters into a textbox in my project. Any suggestions on how I can accomplish this? ...

Caution: Anticipated the server's HTML to include a corresponding <body> within a <div> tag

Upon checking the console, I noticed a warning message appearing. I am puzzled as to why this is happening since I have two matching <body> tags in my index.js file. The complete warning message reads: Warning: Expected server HTML to contain a matc ...

Utilizing the Command Line/Window feature within Visual Studio Code

As a newcomer to Visual Studio Code, I'm currently using the latest Version: 1.29.1. When I used Matlab, I had access to a script window for writing code, a Command Window for testing code snippets and viewing variable values, as well as a workspace ...