5

I just started playing with Angular 2 and Typescript, and recently came across some behaviour I find quite strange.

My class looks like this:

export class Person{
  id: number;
  name: string;
  height: number;
  weight: number;

  calculateBmi() {
    return (weight/(height*height));
  }
}

When instantiating a new person using object literals, like this:

person: Person = {
    id: 1,
    name: "Jack Johnson",
    height: 180,
    weight: 70
  };

I get a (design time) error in Visual Studio 2017 saying:

Type '{id: number, name: string, height: number, weight: number}' is not assignable to type 'Person' Property 'calculateBmi' is missing in type '{id: number, name: string, height: number, weight: number}'

It also states that it

Cannot convert type '{id: number, name: string, height: number, weight: number}' to type 'Person': Type 'Person' has non-optional property 'calculateBmi' which is not present in type '{id: number, name: string, height: number, weight: number}'.

So it seems that the transpiler regards 'calculateBmi' as a property, not a function. The work around is of course to add a constructor and use that to instantiate the class, but I'd like to learn if there is any way to solve this so I could still use object literals?

Thanx, Jon

BTW.: I'm using Resharper 2017.x but I don't this this is what's causing the error message to appear.

1
  • You're telling TS that person is supposed to be of tye Person. The type Person declares a method calculateBmi. So, every time you have a Person instance, you're supposed to be able to call calculateBmi() on that instance. But your object literal doesn't have such a method. So you're trying to shoot yourself in the foot, and TypeScript prevents you from doing that. As you said, just call a constructor. Commented May 4, 2017 at 6:32

1 Answer 1

5

Your instantiation is wrong. Either call the constructor with new

person: Person = new Person()

Or create a complete object literal

person: Person = {
    id: 1,
    name: "Jack Johnson",
    height: 180,
    weight: 70,
    calculateBmi: function() {...}
  };
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks getjackx, but this means that I would have to define the function every time I'm instantiating the class. This is far from optimal, but might be a trade off using object literals...?
Why would you want to use object literals anyway? If necessary you could write a constructor which accepts literals. Or you don't want the function in the class. You could write a controller or service if needed.
Well, I'm just trying to get to grips with the language.
I come from a C# background and was comparing this to instantiating classes using object initializers, but I guess they're quite different. Thanks for the input getjackx!
@getjackx Why would you want to use object literals anyway? there might be a scenario where we are getting Person object from server over http call and need to map that json to Person type variable. In this scenario we can't access calculateBmi

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.