7

I want to initialize an instance of a class with an object literal not containing all the elements in the class but whose elements are in the class.

class ATest{
    aStr:string;
    aNum:number;

    result(){return this.aStr + this.aNum;}
}
let test=new ATest;

test={aStr:"hello",aNum:12};   // error, result() is missing in the object literal

What is the way to do that assignment exploiting the most of the validations of ts?

test=Object.assign(test,{aStr:"hello",aNom:12});

would work but then you miss the validation of the input fields - see aNom that's wrong but gets in

tru7
  • 6,348
  • 5
  • 35
  • 59

1 Answers1

16

You have an object literal, an instance of a class must be created using new ClassName()

The simplest solution is to add a constructor accepting a Partial<T>

class ATest{
    aStr:string;
    aNum:number;
    constructor(obj: Partial<ATest>) {
        Object.assign(this, obj);
    }
    result(){return this.aStr + this.aNum;}
 }

 let test=new ATest({aStr:"hello",aNum:12});

Inside this new constructor you can do validations of the fields as required.

Titian Cernicova-Dragomir
  • 230,986
  • 31
  • 415
  • 357
  • Yes, but the validations would be at runtime. I was looking for a solution detecting at compile time if that's possible... – tru7 Feb 05 '18 at 12:22
  • 1
    @Joan, The `Partial` is validated at compile time. It forces you to specify members of `T` with the same type. I thought you wanted some extra validations, such as weather `aNum >0` or the like. Do you want all the members to be mandatory ? – Titian Cernicova-Dragomir Feb 05 '18 at 12:26
  • Oh, I was totally unaware of the Partial<> thing! – tru7 Feb 05 '18 at 12:34
  • Thanks! I see that this would not work on a non-literal object: let prms={aStr:"hello",aXXXXNum:12}; let test=new ATest(prms); lets it pass without warning... or I'm missing something? – tru7 Feb 05 '18 at 12:53
  • 1
    @Joan no unfortunately that is true, this is not due to partial though, excess properties on object literals are only checked on assignment of a literal to a variable. So `let prms: Partial={aStr:"hello",aXXXXNum:12}; let test=new ATest(prms); ` is invalid, but your example is valid. Type checks still occur so you can't pass `let prms={aStr:"hello",aNum:'12'}; let test=new ATest(prms);` – Titian Cernicova-Dragomir Feb 05 '18 at 12:56
  • yes, what you suggest let prms:Partial={aStr:"hello",aXXXXNum:12}; seems to be the way to go. Thank you again. – tru7 Feb 05 '18 at 13:34