This TypeScript error occurs when you try to assign a value of type object to a variable or parameter that expects a string. The fix involves either extracting the string value from the object, converting it properly, or correcting the type definitions.
This error appears when TypeScript's type checker detects an attempt to assign a value typed as `object` to something expecting a `string`. TypeScript's structural type system considers these types fundamentally incompatible because `object` represents any non-primitive type (objects, arrays, functions), while `string` is a primitive type. The error commonly occurs when working with JSON data, API responses, function parameters, or React props where the actual data structure doesn't match the declared types. TypeScript enforces strict type safety to prevent runtime errors where you might try to use string methods on an object value. Understanding this error requires knowing that TypeScript uses structural typing - it checks the shape and members of types rather than just their names. Since an object and a string have completely different structures and capabilities, they cannot be used interchangeably without explicit conversion or type refinement.
Examine the TypeScript error message to find which line and variable is causing the issue. The error will show both the source type (object) and the target type (string).
// Error location example
const name: string = userObject; // ❌ Type 'object' is not assignable to type 'string'Add a console.log or debugger to inspect what the actual value contains at runtime. This helps you understand the object's structure and identify which property should be extracted.
If you need a specific string value from the object, access that property directly:
// Before - assigning entire object
interface User {
name: string;
email: string;
}
const user: User = { name: 'Alice', email: '[email protected]' };
const username: string = user; // ❌ Error
// After - extract the string property
const username: string = user.name; // ✅ WorksFor nested properties, use dot notation or optional chaining:
const displayName: string = user.profile?.displayName ?? user.name;If you genuinely need to convert an object to a string, use an appropriate conversion method:
// Serialize to JSON string
const configObject = { theme: 'dark', language: 'en' };
const configString: string = JSON.stringify(configObject);
// Convert to string representation
const obj = { id: 123, status: 'active' };
const objString: string = obj.toString(); // "[object Object]" - usually not useful
// Custom string conversion
const objString: string = `ID: ${obj.id}, Status: ${obj.status}`;Note that toString() on plain objects usually returns "[object Object]", which is rarely useful. Use JSON.stringify() or create a custom formatting function instead.
If the type annotation is wrong, update it to match the actual data structure:
// Before - incorrect type
function getUserData(): string {
return { name: 'Alice', email: '[email protected]' }; // ❌ Error
}
// After - correct type
function getUserData(): { name: string; email: string } {
return { name: 'Alice', email: '[email protected]' }; // ✅ Works
}
// Or use an interface
interface UserData {
name: string;
email: string;
}
function getUserData(): UserData {
return { name: 'Alice', email: '[email protected]' };
}If you're certain about the actual type but TypeScript infers it incorrectly, use a type assertion:
// When working with unknown types from external sources
function processData(data: unknown) {
// Option 1: Type assertion
const message = data as string;
// Option 2: Type guard (safer)
if (typeof data === 'string') {
const message: string = data; // TypeScript now knows it's a string
console.log(message.toUpperCase());
}
}Warning: Type assertions bypass TypeScript's type checking. Only use them when you're absolutely certain of the runtime type. Type guards (like typeof checks) are safer because they verify the type at runtime.
If the value could be either an object or a string, use type narrowing:
type StringOrObject = string | { toString(): string };
function handleValue(value: StringOrObject): string {
// Type guard to narrow the type
if (typeof value === 'string') {
return value;
}
// If it's an object, convert it
return value.toString();
}
// Alternative with type predicates
function isString(value: unknown): value is string {
return typeof value === 'string';
}
function processValue(value: string | object): string {
if (isString(value)) {
return value; // TypeScript knows it's a string here
}
return JSON.stringify(value);
}Understanding the `object` type: TypeScript has multiple ways to represent objects. The lowercase object type represents any non-primitive type (introduced in TypeScript 2.2), while Object (capital O) is the type of all instances of the Object class. The empty object type {} represents any value except null and undefined. These distinctions matter when working with generics and type constraints.
Structural typing implications: TypeScript uses structural typing (duck typing) rather than nominal typing. This means types are compatible based on their structure, not their names. An object type has no guaranteed properties that would make it compatible with string, hence the error. This is different from languages like Java where you might cast between types.
Working with JSON and APIs: When working with external data sources, consider using libraries like Zod or io-ts for runtime type validation. TypeScript only provides compile-time type safety, but API responses can change or be malformed. Runtime validation ensures the data actually matches your expected types:
import { z } from 'zod';
const UserSchema = z.object({
name: z.string(),
email: z.string(),
});
const response = await fetch('/api/user');
const data = await response.json();
const user = UserSchema.parse(data); // Validates at runtime
const name: string = user.name; // Safe to useGeneric type constraints: When writing generic functions, you can use type constraints to ensure compatibility:
// Constrain T to have a toString method
function stringify<T extends { toString(): string }>(value: T): string {
return value.toString();
}
// Or constrain to only accept certain types
function processString<T extends string>(value: T): string {
return value; // T must be string or string literal
}Template literal types: TypeScript 4.1+ supports template literal types, which can help create more precise string types:
type EmailString = `${string}@${string}.${string}`;
function sendEmail(address: EmailString) {
// address is guaranteed to be a string
}Function expression requires a return type
Function expression requires a return type
Value of type 'string | undefined' is not iterable
How to fix "Value is not iterable" in TypeScript
Type 'undefined' is not assignable to type 'string'
How to fix "Type undefined is not assignable to type string" in TypeScript
Type narrowing from typeof check produces 'never'
How to fix "Type narrowing produces never" in TypeScript
Type parameter 'T' has conflicting constraints
How to fix "Type parameter has conflicting constraints" in TypeScript