1

I have question about objects. I would like save values from form to precise class object.

For example. I have class TAX

export class TAX
{
    public name: string;
    public description?: string;
    public value: number;
    public enabled: boolean = true;
}

The data that I received from form:

{name: "2000", value: "5", enabled: true, description: "adfdasfdasfasd"}

Now I would like to create new variable of type TAX with data from "simple" object. Is there any build-in function/method or something like that?

I have this solution only:

let entity: TAX = Object.assign(new TAX(), this.form.value);

Is it the best way?

2
  • Your method "works", provided there's no funny business going on with the class, but isn't type-safe. Commented Nov 25, 2019 at 21:01
  • Possibly related: stackoverflow.com/questions/22885995/… Commented Nov 25, 2019 at 21:02

2 Answers 2

1

You can use type assertions to convince the compiler to treat your form as an instance of that class.

const entity = this.form.value as TAX;

Sometimes you’ll end up in a situation where you’ll know more about a value than TypeScript does. Usually this will happen when you know the type of some entity could be more specific than its current type.

Type assertions are a way to tell the compiler “trust me, I know what I’m doing.” A type assertion is like a type cast in other languages, but performs no special checking or restructuring of data. It has no runtime impact, and is used purely by the compiler. TypeScript assumes that you, the programmer, have performed any special checks that you need.

I do this frequently in my Angular projects. Typically I'll have a service method that may accept a certain type (usually a model) as an input. I structure my form to match the shape of the input type and then use type assertion on the form value.

Make sure you validate your form before doing this.

Sign up to request clarification or add additional context in comments.

4 Comments

In this case you wouldn't know better than the compiler, you'd straight out lie to it and should yourself in the foot in the process. instanceof would fail to work, yiu can't use any class methods, ...
Yes -- Great points about instanceof and class methods. It's not really an instance of that class. These may be harmless concerns if you're simply doing this with an anemic model class to shuttle some fields around.
In that case you can just use an interface, though.
Yeah, I no argument here. Interface would be best.
1

If you're declaring a class without the intent to use instanceof or member methods, what you most likely want is just an interface, which would also happen to simplify your logic. The only downside with an interface is that you can't use field initializers like enabled: boolean = true;

export interface Tax {
    name: string;
    description?: string;
    value: number;
    enabled?: boolean;
}

...

const entity: Tax = this.form.value/* as Tax */;

In TypeScript, this is the more conventional solution to your problem, since the only purpose of your awkward Object.assign(new Tax(), ...) was to satisfy the type-check of your class declaration when you really just needed an interface instead.


If in fact you do need to use instanceof or member methods, I would instead suggest adding an analogous interface, and create a constructor for your class:

export interface ITax {
    name: string;
    description?: string;
    value: number;
    enabled?: boolean;
}

export class Tax implements ITax {
    name: string;
    description: string | undefined;
    value: number;
    enabled: boolean;

    constructor ({ name, description, value, enabled = true }: ITax) {
        this.name = name;
        this.description = description;
        this.value = value;
        this.enabled = enabled;
    }
};

...

const entity: Tax = new Tax(this.form.value/* as ITax */);

This way, you're not lying about the type of this.form.value or entity.

Some would argue that it's bad practice to have interfaces with I prefixes in TypeScript, but in this particular case I would argue it makes sense to have because your this.form.value is a plain object that implements the interface, while Tax denotes a proper instance of the respective class, which allows language constructs like instanceof checks, access to member methods, etc., that are not part of the base interface ITax.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.