Description
Proposal: support user-defined type assertions (keyword as
) in addition to user-defined type guards (keyword is
).
A user-defined type assertion is a function with a return type expressed as in the following example (continuing the handbook example in "Advanced Types").
function assertIsFish(pet: Fish | Bird): pet as Fish {
if (!isFish(pet))
throw new Error("birds are not supported");
}
assertIsFish(pet);
pet.swim();
:pet as fish
means that, if the function assertIsFish returns without throwing, pet is automatically asserted to be of type Fish
.
Use-cases:
-
Validators: user-defined type assertions make it possible to encapsulate in functions the type narrowing that is currently available through control flow analysis. They also allow types that better describe the behavior of many existing libraries, including: node asserts, data validators that throw detailed errors, many test frameworks.
-
Polyfills: enables describing functions that modify objects by adding new properties.
addName<T>(obj: T): obj as T & { name: string } {
obj.name = "Mike";
}
const obj = {};
addName(obj);
obj.name.indexOf("i");
Validator examples:
simple undefined checking
function notUndefined<T>(obj: T | undefined): obj as T {
if (obj === undefined)
throw new Error("invalid object");
}
const myObj: string | undefined = {} as any;
// [ts] Object is possibly 'undefined'.
myObj.indexOf("");
notUndefined(myObj);
// no errors
myObj.indexOf("");
joi-like validation currently requires implementing the schema description of an object for runtime checking and copying the schema to an interface to have static type checking while the static type could be inferred by the implementation of the schema
interface Schema<T> {
validate(obj: any): obj is T;
}
function attemptValidation<T>(obj: any, schema: Schema<T>): obj as T {
if (!schema.validate(obj))
throw new Error("very detailed object validation error");
}
// complex schema implements T and T is inferred by the schema construction
// this is already possible
const complexSchema = Joi.object({
myField: Joi.date().iso()
});
attemptValidation(objFromTheRealWorld, complexSchema);
const day = objFromTheReadWorld.myField.getDay();