-1

I have a generic class, which gets some interface as type parameter called DataType. I know that all fields of passed interface are optional (but don't know how to inform ts about this) so I want to initialize private field data with empty object, because in the beginning it is always empty but can be filled with some values

class Basic<DataType extends {}> {
  private data: DataType = {} // this line throws ts2322 error
}

class Man extends Basic<{ firstName?: string, age?: number }> {}
class Animal extends Basic<{ name?: string, isPet?:boolean }> {}

but get an error ts2322

Type '{}' is not assignable to type 'DataType'. '{}' is assignable to the constraint of type 'DataType', but 'DataType' could be instantiated with a different subtype of constraint '{}'

Can this problem be solved?

Dmitry Reutov
  • 2,995
  • 1
  • 5
  • 20
  • You should take a look at TypeScript's Utility Types: https://www.typescriptlang.org/docs/handbook/utility-types.html – Dai Dec 30 '20 at 19:09
  • Why do you think you need to initialize `data` inside `Basic`? (Hint: you don't) – Dai Dec 30 '20 at 19:09
  • There are [over 1000 questions which mention TS2322](https://stackoverflow.com/search?q=ts2322). Please at least look through a couple and say how the answers presented for them don't fit your question. – Heretic Monkey Dec 30 '20 at 19:16
  • @Dai, where i should initialize a class member? Outside of class? I've heard that typescript is different from javascript but didn't think that so far – Dmitry Reutov Dec 30 '20 at 19:34
  • Please read [ask]. The first section is titled "Search, and research..." I don't believe it is arrogant to ask people to do some research and try to answer their own questions before asking others to do the same. See also the FAQ [How much research effort is expected of Stack Overflow users?](https://meta.stackoverflow.com/q/261592/215552) – Heretic Monkey Dec 30 '20 at 20:08
  • @HereticMonkey I don't think that is the answer to this specific question. What OP is ultimately looking for is an object type with all optional properties. – Explosion Pills Dec 30 '20 at 20:49
  • @ExplosionPills which I'm sure has been answered before... – Heretic Monkey Dec 30 '20 at 20:50
  • @Dai, actually thanks a lot for link to utility-types page, it helps me – Dmitry Reutov Dec 30 '20 at 21:07

1 Answers1

1

This specific issue is saying that while DataType fulfills {}, the reverse may not be true since you can implement the generic as something that fits the constraint of {} (an object), but is of a different type. For example, if you had DataType be of type { firstName: string }, you would not be able to assign {} to it. TypeScript does this for type safety... there is no way to know ahead of time whether the generic type will be incompatible with {}.

It appears that what you actually want is for data not to be of DataType, but to be compatible with DataType but with all properties optional. This can be achieved with the Partial type:

private data: Partial<Datatype> = {};
Explosion Pills
  • 188,624
  • 52
  • 326
  • 405
  • You know you can edit your answers, right? There's no need to delete the answer and write a whole new one... – Heretic Monkey Dec 30 '20 at 20:49
  • Interesting, thanks, but is there any way to check may be using js code that all properties of DataType has question mark, which means they are optional? – Dmitry Reutov Dec 30 '20 at 20:50
  • 1
    @DmitryReutov optional properties are strictly related to types / TypeScript. In JavaScript, all properties are optional. Note that because of how `Partial` works, it doesn't matter whether any of the properties you declare for `DataType` are optional or not. `Partial` will make them optional. – Explosion Pills Dec 30 '20 at 20:51
  • @ExplosionPills, Okay, i will research more abot Partial to understand if it is solution or better just assign as `data = {} as DataType` – Dmitry Reutov Dec 30 '20 at 20:57
  • @DmitryReutov these are different approaches; if you cast, then TypeScript will not warn you if the properties are not optional. For example, `data.property` could be undefined, so `data.property.subproperty` would be a runtime error. The `Partial` approach will warn you that `data.property` is possibly undefined during type checking. – Explosion Pills Dec 30 '20 at 21:01
  • @ExplosionPills, Ok, but my basic class doesn't know subproperties so it will return just properties to child class, which knows subproperties. Thanks a lot, very useful. – Dmitry Reutov Dec 30 '20 at 21:06