3

In angular 18 I have usual TypeScript ("module": "ES2022")

I have basic class:

class Item {
  id: number = 0;
  title: string = '';
  active: boolean = false;
  date: Date = new Date();

  getTitle() {
    return this.title;
  }
}

And some object (from Json for example):

const someObj = {
  id: 1,
  title: 'some title',
  active: 1 // notice that type here in number, not boolean
}

I want to create new object with class Item, with all methods available, and with all properties from someObj casted to types from class.

I tried:

const realItem = new Item();
const myItem = <Item> someObj;
const myItem2 = someObj as Item;
const myItem3 = <Item> someObj as Item;
const myItem4 = Object.assign(new Item(), someObj);
console.log(realItem)
console.log(myItem);
console.log(myItem2);
console.log(myItem3);
console.log(myItem4);

None of this ways gives the real Class object, like realItem.

enter image description here

And of course, the method getTitle is not available this way.

The only way I see, to make huge constructor, with checking types:

  constructor(res: any = {}) {
    Object.keys(res).forEach(key => {
      if (this.hasOwnProperty(key)) {
        const type = typeof this[key as keyof typeof this];
        if (type === 'boolean') {
          // @ts-ignore
          this[key as keyof typeof this] = !!res[key];
        } else if (type === 'number') {
          // @ts-ignore
          this[key as keyof typeof this] = +res[key];
        } else if (type === 'string') {
          // @ts-ignore
          this[key as keyof typeof this] = String(res[key]);
        } else if (type === 'object' && this[key as keyof typeof this] instanceof Date) {
          // @ts-ignore
          this[key as keyof typeof this] = new Date(res[key]);
        } else {
          this[key as keyof typeof this] = res[key];
        }
      }
    })
  }

But I can't believe , that there is no simple and right way to do this.

2
  • 1
    It's impossible. TypeScript doesn't exist at runtime. The "casting" operation is just a type assertion, it has not runtime effect. If you want to get a class instance you have to call the class constructor, and if the data you want to copy in is of the wrong type you need to write your own conversion code (because only TypeScript cares about active being a boolean and not a number, and TypeScript is gone when that code runs). JS doesn't have a strong enough type system to do this sort of runtime stuff. You have to write it yourself, sorry. See the linked q/a for more info. Commented Aug 30, 2024 at 13:05
  • (see prev comment) Screenshots of IDEs are unfortunately not appropriate here. Please replace images of code/logs/errors/tooltips with plaintext versions. Commented Aug 30, 2024 at 13:06

1 Answer 1

1

There is no concept of casting in TypeScript nor is there in JavaScript. A class is merely an object with a custom prototype that comprises the defined methods.

In your case, I suggest instantiating the class and assigning all properties from the source object using the built-in Object.assign() utility.

const someObj = { ... }
const obj = Object.assign(new Item(), someObj)
Sign up to request clarification or add additional context in comments.

1 Comment

Yes, I forget about this example, also this does not convert fields types. Updated story.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.