You can declare functions that serve as type guards using any logic you'd like.
They take the form:
function functionName(variableName: any): variableName is DesiredType {
// body that returns boolean
}
If the function returns true, TypeScript will narrow the type to DesiredType
in any block guarded by a call to the function.
For example (try it):
function isString(test: any): test is string {
return typeof test === "string";
}
function example(foo: any) {
if (isString(foo)) {
// foo is type as a string in this block
console.log("it's a string: " + foo);
} else {
// foo is type any in this block
console.log("don't know what this is! [" + foo + "]");
}
}
example("hello world"); // prints "it's a string: hello world"
example({ something: "else" }); // prints "don't know what this is! [[object Object]]"
A guard's function type predicate (the foo is Bar
in the function return type position) is used at compile time to narrow types, the function body is used at runtime. The type predicate and function must agree, or your code won't work.
Type guard functions don't have to use typeof
or instanceof
, they can use more complicated logic.
For example, this code determines if you've got a jQuery object by checking for it's version string.
function isJQuery(foo): foo is JQuery {
// test for jQuery's version string
return foo.jquery !== undefined;
}
function example(foo) {
if (isJQuery(foo)) {
// foo is typed JQuery here
foo.eq(0);
}
}