> ## Documentation Index
> Fetch the complete documentation index at: https://sonamu.cartanova.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Type Errors

> Resolving type errors

This covers common TypeScript type-related errors in Sonamu and how to resolve them.

## Reserved Keywords Collision

### Symptoms

```typescript theme={null}
class UserModelClass extends BaseModelClass {
  async delete(id: number) {
    // ❌
    // delete is a JavaScript reserved keyword
  }
}
```

Runtime error:

```bash theme={null}
Unexpected token 'delete'
```

Or during Sonamu sync:

```bash theme={null}
Error: Reserved keyword 'delete' cannot be used as method name
```

### Cause

Used JavaScript/TypeScript reserved keywords as method or property names.

### Solution

Avoid using reserved keywords or use different names:

```typescript theme={null}
// ❌ Using reserved keywords
async delete() { }
async switch() { }
async return() { }

// ✅ Use different names
async remove() { }
async del() { }
async toggle() { }
async getReturn() { }
```

**72 reserved keywords validated by Sonamu:**

```typescript theme={null}
const RESERVED_KEYWORDS = [
  "break",
  "case",
  "catch",
  "class",
  "const",
  "continue",
  "debugger",
  "default",
  "delete",
  "do",
  "else",
  "enum",
  "export",
  "extends",
  "false",
  "finally",
  "for",
  "function",
  "if",
  "import",
  "in",
  "instanceof",
  "new",
  "null",
  "return",
  "super",
  "switch",
  "this",
  "throw",
  "true",
  "try",
  "typeof",
  "var",
  "void",
  "while",
  "with",
  "yield",
  "let",
  "static",
  "implements",
  "interface",
  "package",
  "private",
  "protected",
  "public",
  "await",
  "abstract",
  "as",
  "asserts",
  "any",
  "async",
  "boolean",
  "constructor",
  "declare",
  "get",
  "infer",
  "is",
  "keyof",
  "module",
  "namespace",
  "never",
  "readonly",
  "require",
  "number",
  "object",
  "set",
  "string",
  "symbol",
  "type",
  "undefined",
  "unique",
  "unknown",
  "from",
  "of",
];
```

## Type Inference Failure

### Symptoms

```typescript theme={null}
const users = await UserModel.findMany();
// Type: any[]  ❌ Type not properly inferred
```

### Causes

1. Sonamu syncer didn't run properly
2. `.generated` file is outdated
3. TypeScript server cache issue

### Solutions

#### 1. Re-run Syncer

```bash theme={null}
pnpm sonamu sync
```

#### 2. Restart TypeScript Server

**VSCode:**

```
Command Palette (Cmd+Shift+P)
> TypeScript: Restart TS Server
```

#### 3. Check Generated Files

```typescript theme={null}
// src/application/sonamu.generated.ts
export type UserSave = {
  id?: number;
  email: string;
  name: string;
  // ...
};
```

If file is missing or outdated, re-run sync.

## BaseModel Method Type Error

### Symptoms

```typescript theme={null}
class UserModelClass extends BaseModelClass {
  async findByEmail(email: string) {
    return this.findOne({ email });
    // Error: Property 'findOne' does not exist on type 'UserModelClass'
  }
}
```

### Cause

BaseModel's auto-generated method types are not properly applied.

### Solutions

#### 1. Check entity.json

```json theme={null}
{
  "properties": {
    "id": { "type": "id" },
    "email": { "type": "string" },
    "name": { "type": "string" }
  }
}
```

#### 2. Check Model Class Definition

```typescript theme={null}
class UserModelClass extends BaseModel<User, UserSave> {
  entityName = "User" as const;
  // ...
}

export const UserModel = new UserModelClass();
```

#### 3. Regenerate Types with Syncer

```bash theme={null}
pnpm sonamu sync
```

## Union Type Error

### Symptoms

```typescript theme={null}
type OrderStatus = "pending" | "processing" | "completed";

class OrderModelClass extends BaseModelClass {
  async updateStatus(id: number, status: string) {
    // ❌
    // status should be OrderStatus
  }
}
```

Type safety is not guaranteed.

### Solution

Specify explicit type:

```typescript theme={null}
type OrderStatus = "pending" | "processing" | "completed";

class OrderModelClass extends BaseModelClass {
  async updateStatus(id: number, status: OrderStatus) {
    // ✅
    return this.updateOne({ id }, { status });
  }
}
```

## Zod Schema Type Mismatch

### Symptoms

```typescript theme={null}
const UserSchema = z.object({
  email: z.string(),
  age: z.number()
});

@api()
async createUser(email: string, age: string) {  // ❌ age should be number
  // ...
}
```

### Cause

API method parameter type doesn't match Zod schema.

### Solutions

#### 1. Fix Parameter Type

```typescript theme={null}
@api()
async createUser(email: string, age: number) {  // ✅
  // Sonamu automatically validates with Zod
}
```

#### 2. Use Explicit Zod Schema

```typescript theme={null}
const CreateUserSchema = z.object({
  email: z.string().email(),
  age: z.number().int().positive()
});

@api({ schema: CreateUserSchema })
async createUser(data: z.infer<typeof CreateUserSchema>) {
  // Type safety guaranteed
}
```

## Intersection Type Error

### Symptoms

```typescript theme={null}
type WithTimestamps = {
  created_at: Date;
  updated_at: Date;
};

type User = {
  id: number;
  email: string;
} & WithTimestamps; // Intersection type

// Type displayed complexly
```

### Solution

From Sonamu 0.7.29+, intersection/union types are automatically wrapped with parentheses:

```typescript theme={null}
// Generated type
type User = {
  id: number;
  email: string;
} & WithTimestamps; // Parentheses added for clarity
```

Re-run sync after update:

```bash theme={null}
pnpm add sonamu@latest
pnpm sonamu sync
```

## Template Literal Type Error

### Symptoms

```typescript theme={null}
type EventName = `user:${string}`;

// Error when using template literal type with Zod v4
```

### Cause

Zod v4 changed how template literal types are handled.

### Solution

Sonamu automatically handles backslash escaping:

```typescript theme={null}
// entity.json
{
  "columns": {
    "event_name": {
      "type": "string",
      "literalType": "user:${string}"  // Automatically handled
    }
  }
}
```

Generated Zod schema:

```typescript theme={null}
z.literal(`user:$\{string}`); // Properly escaped
```

## Circular Reference Type Error

### Symptoms

```typescript theme={null}
// user.model.ts
export class UserModelClass extends BaseModelClass {
  // ...
}
export type User = { ... posts: Post[] };

// post.model.ts
export class PostModelClass extends BaseModelClass {
  // ...
}
export type Post = { ... author: User };

// Error: Circular dependency detected
```

### Cause

Two entities reference each other, causing circular dependency.

### Solutions

#### 1. Use Type-only Import

```typescript theme={null}
// user.model.ts
import type { Post } from "../post/post.model";

export type User = {
  id: number;
  email: string;
  posts: Post[];
};
```

```typescript theme={null}
// post.model.ts
import type { User } from "../user/user.model";

export type Post = {
  id: number;
  title: string;
  author: User;
};
```

#### 2. Create Common Types File

```typescript theme={null}
// types/index.ts
export type { User } from "../application/user/user.model";
export type { Post } from "../application/post/post.model";
```

```typescript theme={null}
// Use in other files
import type { User, Post } from "@/types";
```

## File Type Error (@upload)

### Symptoms

```typescript theme={null}
@upload()
async uploadFile() {
  const { bufferedFiles } = Sonamu.getContext();
  const file = bufferedFiles?.[0];

  const buffer = file.buffer;  // ❌ file may be undefined
}
```

### Cause

The type of `bufferedFiles?.[0]` is `BufferedFile | undefined`, so accessing a property without a null check causes a type error.

### Solution

```typescript theme={null}
@upload()
async uploadFile() {
  const { bufferedFiles } = Sonamu.getContext();
  const file = bufferedFiles?.[0];

  if (!file) {
    throw new BadRequestException("File is required");
  }

  // ✅ Access buffer after null check
  const buffer = file.buffer;

  // Or save file
  const md5 = await file.md5();
  const url = await file.saveToDisk("fs", `uploads/${md5}.${file.extname}`);

  return { url, size: file.size };
}
```

## Type Guard Error

### Symptoms

```typescript theme={null}
function isUser(value: any): boolean {
  // ❌
  return value && typeof value.id === "number";
}

if (isUser(data)) {
  console.log(data.email); // Error: Property 'email' does not exist
}
```

### Cause

Type guard function doesn't perform type narrowing.

### Solution

Use type predicate:

```typescript theme={null}
function isUser(value: any): value is User {
  // ✅
  return value && typeof value.id === "number" && typeof value.email === "string";
}

if (isUser(data)) {
  console.log(data.email); // ✅ Type safe
}
```

## Generic Type Inference Failure

### Symptoms

```typescript theme={null}
async function fetchData<T>(url: string): Promise<T> {
  const response = await fetch(url);
  return response.json(); // Type: any
}

const users = await fetchData("/api/users");
// Type: unknown  ❌
```

### Solution

Specify explicit type:

```typescript theme={null}
const users = await fetchData<User[]>("/api/users");
// Type: User[]  ✅
```

Or type validation:

```typescript theme={null}
async function fetchData<T>(url: string, validator: (data: unknown) => data is T): Promise<T> {
  const response = await fetch(url);
  const data = await response.json();

  if (!validator(data)) {
    throw new Error("Invalid data format");
  }

  return data;
}

// Usage
const users = await fetchData("/api/users", isUserArray);
```

## Related Documentation

* [TypeScript Configuration](/en/configuration/typescript/tsconfig)
* [Type Checking](/en/configuration/typescript/type-checking)
* [Zod Validation](/en/api-development/validation)
* [Auto-generated Services](/en/frontend-integration/generated-services/how-services-work)
