Hi Cyril,
Thank you for starting the discussion.
All of your cases hold. Notes:
1) Of the built-in types, t("JSON"), the wildcard, is the only one that accepts null. In JSON, there are two common ways to represent null values, using "null" and using a JSON object with an omitted field. Teleport chooses the second option and enforces it by keeping null out of the built-in types. It's not that the second option is so superior to the first, it's more about consistency. This only concerns the built-in types, nothing is stopping you from implementing custom types that use null (in fact, I think I'm gonna use null for PATCH representations).
2,3,4) If I understand you correctly, the common theme here is empty arrays and objects being valid Arrays, Maps and Structs and yes, they are. Another JSON ambiguity: if you have an object with an array field and that array is empty, do you include it in the object or do you omit it? Teleport's design suggests that you include it, that is, make it "required" and send an empty array or object if you need to. In some cases, you might have two distinct states: totally-non-existent and exists-but-empty, in which case you should make it optional, but I think this is rather rare in practice.
4) t({"Struct": {"required": { }, "optional": { }}}) is a set with a single JSON value: the empty object. It certainly is a useless schema but it is legal.