Question
Runtime Interface Type Checks in TypeScript: Why `instanceof` Does Not Work
Question
In TypeScript, how can I determine at runtime whether a variable of type any matches an interface?
For example:
interface A {
member: string;
}
let a: any = { member: "foobar" };
if (a instanceof A) {
alert(a.member);
}
In the TypeScript Playground, the last line produces an error saying that A does not exist in the current scope. That seems confusing, because A is clearly declared and can be used in a type annotation like this:
let a: A = { member: "foobar" };
Looking at the generated JavaScript makes the issue clearer:
var a = {
member: "foobar"
};
if (a instanceof A) {
alert(a.member);
}
There is no runtime JavaScript value called A for the interface, so the runtime check cannot work.
I understand that JavaScript does not have interfaces at runtime. Is there any way to check whether an object conforms to an interface shape at runtime in TypeScript? Also, TypeScript seems to have an implements keyword or method in autocomplete—how is that actually used?
Short Answer
By the end of this page, you will understand why TypeScript interfaces disappear at runtime, why instanceof only works with classes and constructor functions, and how to perform safe runtime checks using type guards, property checks, and validation functions.
Concept
TypeScript has two worlds:
- Type world: used by the compiler for checking your code
- Runtime world: actual JavaScript values that exist when the program runs
An interface belongs only to the type world. It helps TypeScript verify that an object has the required shape during development, but it does not generate JavaScript code.
That is why this does not work:
interface A {
member: string;
}
const a: any = { member: "foobar" };
// Error: A is not a runtime value
if (a instanceof A) {
console.log(a.member);
}
instanceof is a runtime operator. It checks whether an object was created by a specific constructor function or class.
For example, this works because User exists at runtime:
class User {
constructor(public member: ) {}
}
u = ();
.(u );
Mental Model
Think of a TypeScript interface like a blueprint drawn on paper.
- While designing the program, the blueprint is useful.
- Once the building is finished, the blueprint is not part of the building.
At runtime, JavaScript only sees the finished building—the actual objects.
So if you ask JavaScript, "Was this object built from interface A?", it cannot answer, because the interface blueprint is gone.
A class is different. A class is more like a factory machine that still exists at runtime. That is why JavaScript can ask:
- "Was this object created by this factory?" →
instanceof
For interfaces, you instead ask:
- "Does this object have the properties I expect?"
Syntax and Examples
Core idea
Use a type guard function to check whether a value matches the structure of an interface.
Interface
interface A {
member: string;
}
Type guard
function isA(value: any): value is A {
return (
value !== null &&
typeof value === "object" &&
typeof value.member === "string"
);
}
Usage
const a: any = { member: "foobar" };
if (isA(a)) {
console.log(a.member); // TypeScript now knows a is A
} else {
console.log("Not an A");
}
Why works for classes only
Step by Step Execution
Consider this code:
interface A {
member: string;
}
function isA(value: unknown): value is A {
return (
typeof value === "object" &&
value !== null &&
"member" in value &&
typeof (value as { member: unknown }).member === "string"
);
}
const input: unknown = { member: "hello" };
if (isA(input)) {
console.log(input.member);
}
Step-by-step
-
interface Adefines the expected shape:- there must be a
member membermust be a string
- there must be a
-
inputis declared as .
Real World Use Cases
Runtime shape checks are common whenever data comes from outside your program.
API responses
interface UserDto {
id: number;
name: string;
}
When you fetch JSON from an API, TypeScript cannot guarantee the server sent the correct shape. A runtime guard can verify it before use.
Local storage or session storage
Data read from storage may be missing fields, have old formats, or contain corrupted values.
Form input processing
User input is unpredictable. You may need to confirm that an object contains the required fields before processing it.
Parsing JSON
const parsed: unknown = JSON.parse(text);
After parsing, runtime validation is often necessary before treating the data as a known interface.
Plugin systems or configuration files
Apps often load configuration from external files. Checking shape at runtime helps prevent crashes.
Message passing
In frontend apps, workers, browser events, or postMessage payloads may need runtime validation before use.
Real Codebase Usage
In real projects, developers rarely check interfaces directly. Instead, they use a few common patterns.
1. Type guard functions
This is the most common pattern for lightweight validation.
function isA(value: unknown): value is A {
return (
typeof value === "object" &&
value !== null &&
"member" in value &&
typeof (value as { member: unknown }).member === "string"
);
}
2. Guard clauses
Validate early and return quickly.
function printMember(value: unknown) {
if (!isA(value)) {
throw new Error("Expected A");
}
console.log(value.member);
}
This keeps the rest of the function simple.
3. Validation at application boundaries
Common Mistakes
1. Trying to use instanceof with an interface
Broken code:
interface A {
member: string;
}
const a: any = { member: "x" };
if (a instanceof A) {
console.log(a.member);
}
Why it fails:
Ais not a runtime value- interfaces are removed during compilation
Fix:
function isA(value: unknown): value is A {
return (
typeof value === "object" &&
value !== null &&
"member" in value &&
typeof (value as { member: unknown }).member === "string"
);
}
2. Confusing with runtime checking
Comparisons
| Concept | Exists at runtime? | Used for | Example |
|---|---|---|---|
interface | No | Compile-time shape checking | interface A { member: string } |
class | Yes | Creating objects and runtime checks | class AClass { ... } |
instanceof | Yes | Checking class/constructor identity | obj instanceof AClass |
implements | No runtime effect | Ensuring a class matches an interface | class X implements A |
Cheat Sheet
Key rules
- Interfaces are compile-time only in TypeScript.
- Interfaces do not exist in generated JavaScript.
instanceofworks with classes, not interfaces.implementsis used by classes to satisfy an interface at compile time.- For runtime interface-like checks, use a type guard.
Basic pattern
interface A {
member: string;
}
function isA(value: unknown): value is A {
return (
typeof value === "object" &&
value !== null &&
"member" in value &&
typeof (value as { member: unknown }).member === "string"
);
}
Use it like this
const value: unknown = { member: "hello" };
if ((value)) {
.(value.);
}
FAQ
Why does TypeScript say an interface does not exist in the current scope?
Because instanceof expects a runtime value, such as a class or constructor function. An interface is only a compile-time type, so it is not available as a JavaScript value.
Can I use instanceof with an interface in TypeScript?
No. instanceof only works with classes, constructor functions, and objects that exist at runtime.
How do I check whether an object matches an interface?
Write a type guard function that checks the required properties and their types.
Does implements perform runtime checking?
No. implements only tells the TypeScript compiler to verify that a class matches an interface.
Is value as MyInterface a runtime check?
No. A type assertion only changes what TypeScript assumes. It does not inspect the actual data.
Should I use any or unknown for incoming data?
Prefer unknown. It forces you to validate the value before using it.
What should I use for API response validation?
For simple cases, write a type guard. For larger or nested data, use a dedicated validation approach or schema library.
Mini Project
Description
Build a small runtime validator for user profile data. This demonstrates the exact situation where interfaces are useful for compile-time typing, but runtime checks are still necessary when data comes from an untrusted source like JSON or an API response.
Goal
Create a function that safely checks whether unknown input matches a UserProfile interface before using it.
Requirements
- Define a
UserProfileinterface withid,name, andemailfields. - Write a type guard function that validates the object at runtime.
- Test the guard with one valid object and one invalid object.
- Print the user name only when the value passes validation.
Keep learning
Related questions
Angular formGroup Error Explained: Fixing 'Can't bind to formGroup' in Reactive Forms
Learn why Angular shows 'Can't bind to formGroup' and how to fix it by importing ReactiveFormsModule correctly.
Fix "Element implicitly has an 'any' type" in TypeScript Object Indexing
Learn why TypeScript rejects string object indexing and how to fix it with keyof, unions, and typed object keys in React.
Fix "Property has no initializer" in Angular TypeScript Components
Learn why Angular TypeScript shows "Property has no initializer" and how to fix it using defaults, optional properties, or definite assignment.