Good points!
Seems like for "6. Optional properties"
One should rather use tagged unions (see: Abstract Data Types, variants) that are usually written like this in TS:
type Product =
| { type: 'digital', id: string, sizeInMb: number }
| { type: 'physical', id: string, weightInKg: number }
At least I find it more elegant, concise and fun to work with :)Also, for using type guards to validate incoming data, check out https://github.com/pelotom/runtypes.
Or if brave enough to dive into the deep end of FP, io-ts is nice. https://github.com/gcanti/io-ts