Is it possible to create a typeguard, or something else that accomplishes the same purpose, to check if a variable is a specific interface type in a typescript union?
interface Foo { a:string }
interface Bar { b:string }
(function() {
function doStuff(thing: Foo | Bar) {
if(typeof thing === 'Foo') {
console.log('Foo');
}
else if (typeof thing === 'Bar') {
console.log('Bar');
}
else {
console.log('unknown');
}
}
var thing: Foo = {a:'a'};
doStuff(thing);
})();
typeof
doesn't do this. It always return "string", "number", "boolean", "object", "function", or "undefined".You can test for object properties with a test like
if(thing.a !== undefined) {
orif(thing.hasOwnProperty('a')) {
.Note that you could make an object that had both a string
a
and a stringb
, so be aware of that possibility.Since Typescript 1.6 you can use user-defined type guards:
See https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards and https://github.com/microsoft/TypeScript/issues/10485
In TypeScript 2 you can use Discriminated Unions like this:
and then test object using
if (thing.kind === "foo")
.If you only have 2 fields like in the example I would probably go with combined interface as @ryan-cavanaugh mentioned and make both properties optional:
Note that in original example testing the object using
if (thing.a !== undefined)
produces errorProperty 'a' does not exist on type 'Foo | Bar'.
And testing it using
if (thing.hasOwnProperty('a'))
doesn't narrow type toFoo
inside theif
statement.@ryan-cavanaugh is there a better way in TypesScript 2.0 or 2.1?