| "Recovered" sounds so binary. I think it's pretty usuable now, but there is scarring. The solution would have been much nicer had it been around from day one; especially surrounding generics and constraints. It's not _entirely_ sound, nor can it warn about most mistakes when those are in the "here-be-dragons" annotations in generic code. The flow sensitive bit is quite nice, but not as powerful as in e.g. typescript, and sometimes the differences hurt. It's got weird gotcha interactions with value-types, for instance but likely not limited to interaction with generics that aren't constrained to struct but _do_ allow nullable usage for ref types. Support in reflection is present, but it's not a "real" type, and so everything works differently, and hence you'll see that code leveraging reflection that needs to deal with this kind of stuff tends to have special considerations for ref type vs. value-type nullabilty, and it often leaks out into API consumers too - not sure if that's just a practical limitation or a fundamental one, but it's very common anyhow. There wasn't last I looked code that allowed runtime checking for incorrect nulls in non-nullable marked fields, which is particularly annoying if there's even an iota of not-yet annoted or incorrectly annotated code, including e.g. stuff like deserialization. Related features like TS Partial<> are missing, and that means that expressing concepts like POCOs that are in the process of being initialized but aren't yet is a real pain; most code that does that in the wild is not typesafe. Still, if you engage constructively and are willing to massage your patterns and habbits you can surely get like 99% type-checkable code, and that's still a really good help. |
If it's an object, it's as simple as having a static method on a type, like FromA(A value) and then have that static method call the constructor internally after it has assembled the needed state. That's how you'd do it in Rust anyway. There will be a warning (or an error if you elevate those) if a constructor exits not having initialized all fields or properties. Without constructor, you can mark properties as 'required' to prohibit object construction without assignment to them with object initializer syntax too.