How to fix Cannot use 'X' as a value in TypeScript
This error occurs when you try to use a type, interface, or type alias at runtime where a value is expected. In TypeScript, types only exist during compilation and are erased at runtime, so they cannot be used as JavaScript values.
Quick fix
Fixes TS2693
interface User {
id: number;
name: string;
}
// ❌ Error: Cannot use 'User' as a value
if (obj instanceof User) {
console.log("It's a User");
}- Identify the problematic type usage
- Convert the interface to a class (if possible)
- Create a user-defined type guard function
- Use type-only imports if applicable
interface User {id: number;name: string;}// ❌ Error: Cannot use 'User' as a valueif (obj instanceof User) {console.log("It's a User");}Cannot use 'X' as a value
What this error means
TypeScript has two separate namespaces: types and values. Type definitions (interfaces, type aliases, abstract classes) exist only during compilation and are completely removed when your TypeScript code is transpiled to JavaScript. When you try to use a type name in a context that requires a runtime value—such as with the `instanceof` operator, function calls, or object properties—TypeScript throws this error because that type name doesn't exist as a value at runtime. For example, you can use `Employee` as a type annotation in `let emp: Employee`, but you cannot use it as a value in `instanceof Employee` because there's no actual JavaScript value to check against.
Typical symptoms
- Error message: 'X' only refers to a type, but is being used as a value here
- Attempting to use instanceof with an interface or type alias
- Trying to pass a type as an argument to a function
- Attempting to use a type name in conditionals or expressions
- Trying to return a type or assign it to a variable
- Using a type with operators like typeof or instanceof
Common causes
- Using instanceof with an interface or type alias instead of a class (most common)
- Trying to use a type name as a function argument or return value
- Confusing type-only imports with regular imports
- Using a namespace or type alias where a value is required
- Attempting to spread or destructure a type
- Using a generic type at runtime without a value wrapper
How to fix "Cannot use 'X' as a value"
First, locate the line causing the error. You'll see something like:
interface User {
id: number;
name: string;
}
// ❌ Error: Cannot use 'User' as a value
if (obj instanceof User) {
console.log("It's a User");
}The error occurs because User is an interface (compile-time only), not a runtime value.
The simplest fix is to change the interface to a class. Classes exist at runtime and can be used with instanceof:
// ✅ Instead of interface, use class
class User {
constructor(
readonly id: number,
readonly name: string
) {}
}
if (obj instanceof User) {
console.log("It's a User");
}Classes provide both type-checking (like interfaces) and runtime values.
If you need to keep the interface, create a runtime function to check the properties:
interface User {
id: number;
name: string;
}
// Define a type guard function
function isUser(obj: unknown): obj is User {
return (
typeof obj === "object" &&
obj !== null &&
"id" in obj &&
"name" in obj &&
typeof (obj as any).id === "number" &&
typeof (obj as any).name === "string"
);
}
// ✅ Use the type guard instead of instanceof
if (isUser(obj)) {
console.log("It's a User");
}If you're importing a type that doesn't exist as a value, ensure you're using import type:
// ✅ Correct - type-only import
import type { User } from "./types";
// Use User only in type annotations, never as a value
let user: User;
// ❌ This would still error
// const UserClass = User; // Can't use User as a valueType-only imports explicitly tell TypeScript to erase the import, preventing accidental runtime usage.
Compile your TypeScript to ensure the error is gone:
npx tsc --noEmitOr run your dev server:
npm run devThe error should now be resolved, and your code will compile successfully.
Advanced notes
### Type Assertion Workaround (Not Recommended)
In some cases, you might see a workaround using type assertions with typeof:
type UserType = typeof SomeClass;This only works when there's an underlying value (like a class). For pure interfaces, this approach fails.
### Discriminated Unions as a Type-Safe Alternative
Instead of relying on instanceof, use discriminated unions for better type safety:
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function getArea(shape: Shape) {
switch (shape.kind) {
case "circle":
return Math.PI * shape.radius ** 2;
case "square":
return shape.side ** 2;
}
}This pattern is more idiomatic in TypeScript and avoids runtime type checking entirely.
### Zod and Runtime Validation Libraries
For complex data validation, consider libraries like Zod, io-ts, or Yup:
import { z } from "zod";
const UserSchema = z.object({
id: z.number(),
name: z.string(),
});
type User = z.infer<typeof UserSchema>;
// ✅ Safe runtime validation
const user = UserSchema.parse(unknownData);These libraries provide both type safety and runtime validation.
### Enum as a Type-Safe Alternative
For a fixed set of values, use enums instead of type unions:
enum UserRole {
Admin = "admin",
User = "user",
Guest = "guest",
}
// Enums exist at runtime, so this works
function checkRole(role: unknown): role is UserRole {
return Object.values(UserRole).includes(role);
}Frequently asked questions
- What does "TS2693" mean?
- TypeScript has two separate namespaces: types and values. Type definitions (interfaces, type aliases, abstract classes) exist only during compilation and are completely removed when your TypeScript code is transpiled to JavaScript. When you try to use a type name in a context that requires a runtime value—such as with the instanceof operator, function calls, or object properties—TypeScript throws this error because that type name doesn't exist as a value at runtime.
- How do I fix "TS2693"?
- This error occurs when you try to use a type, interface, or type alias at runtime where a value is expected. In TypeScript, types only exist during compilation and are erased at runtime, so they cannot be used as JavaScript values.
- What causes "TS2693"?
- Using instanceof with an interface or type alias instead of a class (most common) Trying to use a type name as a function argument or return value Confusing type-only imports with regular imports
- Is the "TS2693" error serious?
- Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.
Official resources & further reading
- 📚TypeScript Official Documentation
- 📖TypeScript Handbook - Everyday Types(Official Docs)
- 📖TypeScript Handbook - Advanced Types(Official Docs)
- 🐙