Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript object casting not working

I got an HTTP API. I am loading a set of objects as a json.

I want to cast to a Typescript object, but with the keyword "as" it is not working and even not with < Type > in front of the object.

r.forEach(entry => {
    entry.creationDate = new Date(entry.creationDate.date);
    entry.creator = <User>entry.creator;
    return entry;
});

The console.log directly after entry.creator casting outputs a normal "Object".

Can someone give me an advice?

like image 482
CodeWarrior Avatar asked Oct 15 '16 18:10

CodeWarrior


People also ask

How do you cast on TypeScript?

To cast something in TypeScript, we use the as keywords. For this example, we need to cast the text variable to a string, so TypeScript will let us use length : let text:unknown = "string"; let value = (text as string).

What does as do in TypeScript?

The as keyword is a Type Assertion in TypeScript which tells the compiler to consider the object as another type than the type the compiler infers the object to be.

How do I compare types in TypeScript?

In Typescript, we have three ways to work with it using: typeof: the keyword helps to check values types, like boolean, string, number, etc. instanceof: the keyword to compare the object instance with a class constructor. type guards: The powerful way to check types using typescript feature language.


2 Answers

I I've struggled with similar problems, and in my opinion this is a defect in typescript. When you are doing the cast as you did. Or a sample code like this:

class User {
    name: string;

    doConsole(): void {
        console.log(`Name: ${this.name}`);
    }
}

let userObj = { name: 'jose' };

let user = new User();
Object.assign(user, userObj);

user.doConsole();

You will notice that doConsole won't be a function in the casted object. That's the generated JS to this:

var User = (function () {
    function User(name) {
        this.name = name;
    }
    User.prototype.doConsole = function () {
        console.log("Name: " + this.name);
    };
    return User;
}());
var userObj = { name: 'jose' };
var user = userObj;
user.doConsole();

As you can see it doesn't uses the prototype function you prepared by the class when doing the cast. My alternative was to do something like this:

class User {
    name: string;

    doConsole(): void {
       console.log(`Name: ${this.name}`);
    }
}

let userObj = { name: 'jose' };

let user = new User();
Object.assign(user, userObj);

user.doConsole();

This ensures that you are using the prototype function, as you can see by the generated JS:

var User = (function () {
    function User() {
    }
    User.prototype.doConsole = function () {
        console.log("Name: " + this.name);
    };
    return User;
}());
var userObj = { name: 'jose' };
var user = new User();
Object.assign(user, userObj);
user.doConsole();

So basically what I'm saying is that I agree with you that it should works like you did, but the transpiler doesn't use the prototyped function, so it won't work.

I hope this helps you.

like image 167
luis.mazoni Avatar answered Nov 15 '22 23:11

luis.mazoni


Javascript itself doesn't support strong typings. You can use strong typing only with Typescript but it only works for compile-time. What you are experiencing on runtime is the expected behaviour. Not a bug or error with your code.

Some of the great features that Typescript provides are:

  • Compile time checking: Find potential errors on your code before your customer does.
  • Strongly-typed objects: By specifying the type of objects your functions expect you can reduce the risk of unexpected results.

Source of my quote and more info about strong typing here.

like image 41
Sefa Avatar answered Nov 15 '22 23:11

Sefa