This helps ensure runtime type safety because (for example) it would be great to have a generic "validation" function that takes an arbitrary interface and an arbitrary object and validates that object. One way to implement this would be to use /compile time/ reflection to generate code (TS code hypothetical, because I write C++ nowadays):
function validate<T>(obj: Any): T | null {
switch constexpr (T) {
case String:
return typeof obj == "string" ? obj : null;
case Array<U>
if (!Array.isArray(obj)) {
return null;
}
for (const u of obj) {
if (validate<U>(u) == null) {
return null;
}
}
return obj;
// ... more base cases
}
for (const prop: (keyof T) of Reflect<T>.Properties()) {
if (validate<T[prop]>(obj[prop]) == null) {
return null;
}
}
return obj;
}
interface Date {
year: String;
month: String;
day: String;
}
It would be great if this could generate /JavaScript/ code: function validate__String__(obj) {
return typeof obj == "string" ? obj : null;
}
function validate__Array$Date$__(obj) {
if (!Array.isArray(obj)) {
return null;
}
for (const u of obj) {
if (validate__Date__(u) == null) {
return null;
}
}
return obj;
}
function validate__Date__(obj) {
for (const prop of ["year", "month", "day"])) {
if (validate__String__(obj[prop]) == null) {
return null;
}
}
return obj;
}
Unfortunately this is not possible (AFAIK) in TypeScript currently, and will not be possible with TypeScript's current philosophy.(The above example is a hypothetical TypeScript compiler that might support "templated" generic functions; with just RTTI TypeScript could accomplish the same thing in a non-templated function by passing in `T` as a function parameter at runtime and doing runtime comparisons on `T`.)