Edit: I want to point out to people coming here from searches that this question is specifically dealing with non-class types, ie object
shapes as defined by interface
or type
alias. For class types you
can use JavaScript's instanceof
to determine the class an instance comes from, and TypeScript will narrow the type in the type-checker automatically.
Types are stripped away at compile-time and do not exist at runtime, so you can't check the type at runtime.
What you can do is check that the shape of an object is what you expect, and TypeScript can assert the type at compile time using a user-defined type guard that returns true (annotated return type is a "type predicate" of the form arg is T
) if the shape matches your expectation:
interface A {
foo: string;
}
interface B {
bar: number;
}
function isA(obj: any): obj is A {
return obj.foo !== undefined
}
function isB(obj: any): obj is B {
return obj.bar !== undefined
}
function func(obj: any) {
if (isA(obj)) {
// In this block 'obj' is narrowed to type 'A'
obj.foo;
}
else if (isB(obj)) {
// In this block 'obj' is narrowed to type 'B'
obj.bar;
}
}
Example in Playground
How deep you take the type-guard implementation is really up to you, it only needs to return true or false. For example, as Carl points out in his answer, the above example only checks that expected properties are defined (following the example in the docs), not that they are assigned the expected type. This can get tricky with nullable types and nested objects, it's up to you to determine how detailed to make the shape check.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…