Description
Motivation
Verify inputs at application boundary.
When a Typescript application interacts with an external system (e.g. receives a Json object from a http request, or receives an object from an external library) a typical approach is to use the cast operator for the input and to assume/hope that the application receives the required type.
If/when the external system changes the assumption can be broken resulting in sometimes hard to find bugs and unhelpful runtime errors like "undefined is not a function".
These bugs are also quite hard to catch in tests since unit tests isolate the external system, only integration tests would be able to catch these scenarios.
Proposal
A new cast operator could be introduced that does structural type checking at runtime.
Example:
$http.get('https://mySite.com/products', ( result: { data: IProduct[] } ) =>{
var data:IProduct[] = dynamic_cast<IProduct[]>result.data;
});
The Typescript compiler could operate in 2 modes ( debug / release or runtime type checks on/off)
In release the compiler would simply remove the dynamic_cast operator.
In debug mode the compiler would wrap the expression in a typeCheck call. It would generate something like this:
$http.get('https://mySite.com/products', function( result ) {
var data:IProduct[] = IProduct.CheckType(result.data);
});
The tricky bit comes in implementing the CheckType() function.
Interfaces that are dynamically checked would suddenly acquire a runtime footprint.
Also any interface and Type that appear as the type of members of any interface and type that are type checked would also need to receive a ChekType static member function.
It would be still nicer if it would be possible to support a syntax like:
$http.get('https://mySite.com/products', ( result: dynamic_cast<{ data: IProduct[] }> ) =>{
var data:IProduct[] = result.data;
});
Although it is not very clear (to me) where would the cast function be scoped and how it would be called, probably the lambda would be wrapped in something ugly like:
$http.get('https://mySite.com/products',
function (result){
return (function( result ) {
var data:IProduct[] = IProduct.CheckType(result.data);
})( ???.CheckType(result));
});