6

This is a more simple example of what I'm trying to do:

export class Person{
    id:Number;
    name:String;
}

export class PersonForm{

    // This line:
    default:Person = {name: "Guy"};
    // Gives the following error:
    //  Error:(25, 5) TS2322: Type '{ name: string; }' is not assignable to type 'Person'.
    //  Property 'id' is missing in type '{ name: string; }'.

    // I tried <Person>{name: "Guy"} but it gives the same error.

}

How can I make the compiler ignore this issue as long as Im not using non existant properties, or how do I declare the class so I can do the assignment this way instead of new Person() and then setting just the properties I want.

Note: Sending an object with all the properties into the constructor is not the solution I'm expecting. Also using an interface works because I can declare the fields optional, how can I do the same in a class?

Adding some more info:

The main goal of what I'm trying to achieve:

Find the best way to declare a class (not an interface) so I can initialize it with clean code in one line setting only the parameters I want to set. In Java you would overload constructors or use the Builder pattern.

I could certainly try the builder pattern but I'm looking for a more typescript way to do it, if there's any.

9
  • 1
    what's wrong with using an interface in this scenario? Seems like the best fit. Commented Dec 30, 2015 at 18:43
  • 1
    I think your options are to create an interface w/the optional property and have your class implement the interface or accept the interface as a constructor parameter. At the moment, there is no way to do what you want, but others have asked for it. Commented Dec 30, 2015 at 18:44
  • alternatively you could just make a constructor for the class and call it with a null parameter.. the interface would still be better for this case though. Commented Dec 30, 2015 at 19:28
  • @toskv This is not the real scenario, just a simple scenario to make it easier to see the one thing I want to do. The real scenario needs a class, as I specified. Commented Dec 30, 2015 at 21:28
  • @SunilD. I already know how to do it with an interface, the question is how to do something similar with a class instead. Commented Dec 30, 2015 at 21:28

4 Answers 4

3

I found the easiest way to do it, and IT IS POSSIBLE. I think I had tried it this way before but the fact that I was using the "Number" & "String" types instead of "number" & "string", might be giving me missleading errors from the compiler, the following code works wonders for me:

export class Person{
    constructor(
        public id?: number, // make sure you use number and string types instead of Number and String types
        public name?: string // make sure you make all properties optional using "?"
    ){}
}

export class PersonForm{
    default:Person = <Person>{name: "Guy"};
}
Sign up to request clarification or add additional context in comments.

2 Comments

<Person>{name: "Guy"} instanceof Person; // false
@JohnWhite yea, {name: "Guy"}'s type is Object, if you want an instance of Person you need to call the constructor: new Person()
0

You could write your class with a constructor.

export class Person {
  constructor(public id: number, public name: string) {}
}

But you would have to call it like this.

let person = new Person(null, "George");

4 Comments

You are setting all parameters there, I want the ability to set only the ones I want. The closest solution I have is using constructors though, so you might be on the right track.
Indeed, well you can use a factory to create the items, but as I said, <Person>{name: "Guy"} works fine for me. What version of typescript are you using?
Hey toskv I hadn't seen this comment, yea apparently the casting was fine, it was just the way to declare the class that was wrong in order to achieve what I wanted, you were on the right track but in your example you are initializing all the properties, change it so it looks like the one I posted and I'll change the accepted answer to yours.
@Langley your answer looks fine. :)
0

Cast the JSON expression to any. The line to assign default becomes:

default: Person = <any>{ name: "Guy" };

Comments

0

This is another option to complement the other answers posted here..

If you have some object initialiser

{
  name:"John" 
}

and you explicitly want an instance of the class Person, but want keep the object initialiser, while keeping the defaults that the class Person creates, you can do it via passing the entire object into the class constructor:

var instance = new Person({name:"John"});

where

export class Person
{
   id:number = 0; //or generate one
   name:string = "unknown";
   constructor(opts:{id?:number; name?:string}){
      if(opts){
          this.id = opts.id || this.id;
          this.name = opts.name || this.name;
      }
   }
}

examples:

var people = [
   new Person(),
   new Person({name:"John"}),
   new Person({name:"James", id:10}),
   new Person({id:20})];

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.