Creating a TypeScript class that includes all the attributes of a pre-existing object type

One technique I frequently use in TypeScript involves transforming a plain JSON object definition into a class during runtime. Here's an example:

export type LessonDef = {
  id: string
  title: string
  slug: string
  shortdesc: string
  explanation: string
  exercises: {
    from: string
    message: string
    translation: string
    hint?: string
    feedback?: { [key: string]: string }
  }[]
}

export class Lesson {
  constructor(readonly def: LessonDef) {
    Object.assign(this, def)
  }

  // Additional methods go here
}

An issue arises when the type system does not recognize the outcome of Object.assign. How can I inform TypeScript that Lesson is an extension of the type LessonDef?

Answer №1

For more information, check out this response

You have the option to combine your class declaration and interface.

Here's an example to consider:

interface Lesson {
    id: string
    title: string
    slug: string
    shortdesc: string
    explanation: string
    exercises: {
        from: string
        message: string
        translation: string
        hint?: string
        feedback?: { [key: string]: string }
    }[]
}

declare let x: Lesson;

class Lesson {
    constructor(def: Lesson) {
        Object.assign(this, def);
    }
}

const result = new Lesson(x)

result.exercises // works fine

Try it out in the playground

@Cerberus, thank you for highlighting my error with using {... def} instead of def

Nevertheless, there is a downside - you may reference this.exercises before Object.assign

class Lesson {
    constructor(def: Lesson) {
        this.exercises //fine, <----- DOWNSIDE!
        Object.assign(this, def);
    }
}

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

Updating the state in React Native does not occur

I'm facing an issue where I can't seem to update the state using useState while coding in React Native. The component in question is a styled TextInput named SearchField. Can anyone help me figure out what I might be doing wrong that's preve ...

Group Hover by StyleX

I recently experimented with the innovative StyleX library and encountered a particular challenge. Can a group hover effect be achieved for a component solely using this library? For instance, let's assume we have the following component in Tailwind ...

Altering the background color of an individual mat-card component in an Angular application

Here is the representation of my mat-card list in my Angular application: <div [ngClass]="verticalResultsBarStyle"> <div class="innerDiv"> <mat-card [ngClass]="barStyle" *ngFor="let card of obs | async | paginate: { id: 'paginato ...

Merging two arrays in Typescript and incrementing the quantity if they share the same identifier

I am currently working on my Angular 8 project and I am facing a challenge with merging two arrays into one while also increasing the quantity if they share the same value in the object. Despite several attempts, I have not been able to achieve the desired ...

The dropdown cannot be disabled because it is being passed as an input parameter

We are currently utilizing PrimeNG along with Angular 15. Scenarios: According to the requirements, we need the ability to disable the PrimeNG dropdown control based on a selection. Problem: The disabled property of <p.dropdown> is not functioning ...

Utilize the useState hook to update state when changes occur in the

I currently have a functional component that utilizes a useState hook. The values it holds are sourced from my redux store, and I aim to update the state with the new store state every time an action is dispatched. At the moment, I've manually set an ...

What is the best way to verify that I am receiving the 'jwt' token in my code?

Trying to understand the data held by the jwt token in my next.js app, but encountering an error message saying error: jwt must be provided. Here's the code snippet causing the issue: import { NextRequest } from "next/server" ...

Error encountered when packaging WebAssembly using Rollup

When I use wasm-pack to compile some rust code into webassembly, specifically with the option --target browser (which is the default), these are the files that I see in typescript/deps/ed25519xp: ed25519xp_bg.wasm ed25519xp_bg.d.ts ed25519xp.d.ts ed25519 ...

Ways to integrate user input into the header of an Angular HTTP post method

I need help figuring out how to incorporate user input into the header of a post method I am working with. I understand that some kind of binding is necessary, but I'm struggling to implement it in this case. Currently, I have a variable called postDa ...

All-encompassing NextJS App router with a focus on Internationalization

I am currently working with a folder structure that includes an optional catch-all feature. The issue I am facing is that the page does not change when the URL is altered to include ""/"" or ""/about-us"". It consistently remains on the ...

What is the best way to pass props to a styled component (e.g., Button) in Material-UI

One of my tasks involves creating a customized button by utilizing the Button component with styled components. export const CustomButton = styled(Button)({ borderRadius: "17px", fontWeight: 300, fontSize: ".8125rem", height: &q ...

Issues with Injectable Service within Another Service in Angular 2

Having a problem with injecting a service into another service. I have a ContactService that retrieves data from the server using the handleError method, and an AlertService that handles errors thrown from the handleError method. Both services are declared ...

Is it possible to access a class with protected/private fields written in TypeScript from outside the class in JavaScript?

Currently, I am delving into TypeScript classes (though my experience with OOP is limited). The following code snippet is extracted from the chapter on classes in https://www.typescriptlang.org/docs/handbook/classes.html Here's the issue at hand: I ...

Explaining the distinction between include and rootDir in tsconfig.json

According to the information provided, include defines an array of filenames or patterns that are to be included in the program during the compilation process. On the other hand, rootDir specifies the path to the folder containing the source code of the ap ...

Implementing a NextJS client component within a webpage

I am currently working with NextJS version 14 and I am in the process of creating a landing page. In one of the sections, I need to utilize the useState hook. I have specified my component as "use-client" but I am still encountering an error stating that " ...

Using Angular and Typescript to implement a switch case based on specific values

I am attempting to create a switch statement with two values. switch ({'a': val_a,'b': val_b}){ case ({'x','y'}): "some code here" break; } However, this approach is not functioning as expected. ...

Typescript: The property 'userId' is not found within the 'unknown' type

For my rxJS practice in Typescript, I wrote the following simple code. import fetch from 'node-fetch'; import { Observable, Subject, asapScheduler, pipe, of, from, interval, merge, fromEvent, SubscriptionLike, PartialObserver } from &apo ...

What are some ways to prevent unnecessary HTML re-rendering when using this.sanitizer.bypassSecurityTrustHtml(value)?

What is the best way to prevent constant HTML re-rendering when utilizing (this.sanitizer.bypassSecurityTrustHtml(value)) in Angular versions 5 and above? ...

Running the nestjs build command is impossible without the existence of the node_modules folder

Currently, I am in the process of creating a Nestjs micro-service and everything is going smoothly. To run the build found within the dist folder, I use the command below: node dist/main.js However, I encountered a problem where this command does not exec ...

Nested interfaces can utilize sum types

An example showcasing the use of sum types: interface Cash { amount: number, type: 'cash' } interface Card { amount: number, type: 'card', cardNumber: string } type Payment = Cash | Card const displayPayment = (payment: Pay ...