> ## 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 Checking

> Configuring compiler options

TypeScript's type checking options determine the stability of your code. Sonamu **enables strict mode by default** to provide maximum type safety.

## Strict Mode

Sonamu enables all strict options.

```json theme={null}
{
  "compilerOptions": {
    "strict": true,                          // Enable all strict options
    "noImplicitAny": true,                   // Require explicit any type
    "strictNullChecks": true,                // Strict null/undefined checking
    "strictFunctionTypes": true,             // Strict function type checking
    "strictBindCallApply": true,             // Strict bind/call/apply checking
    "strictPropertyInitialization": true,    // Require class property initialization
    "noImplicitThis": true,                  // Require explicit this type
    "alwaysStrict": true                     // Auto-add 'use strict'
  }
}
```

<Info>
  `strict: true` is a shortcut that enables all the above options at once.
</Info>

## Strict Options in Detail

<Tabs>
  <Tab title="noImplicitAny" icon="question">
    ### Require Explicit any Type

    **Function:**

    * Prevents implicit use of `any` when type cannot be inferred

    **Example:**

    ```typescript theme={null}
    // ❌ Error
    function log(message) {
      //         ^^^^^^^ Parameter 'message' implicitly has an 'any' type
      console.log(message);
    }

    // ✅ Correct code
    function log(message: string) {
      console.log(message);
    }

    // ✅ Using generics
    function log<T>(message: T) {
      console.log(message);
    }
    ```

    <Tip>
      If typing is difficult, use `unknown`. It's safer than `any`.
    </Tip>
  </Tab>

  <Tab title="strictNullChecks" icon="ban">
    ### Strict null/undefined Checking

    **Function:**

    * Prevents assigning `null` and `undefined` to other types
    * All types are non-nullable by default

    **Example:**

    ```typescript theme={null}
    // ❌ Error
    let name: string = null;
    //                 ^^^^ Type 'null' is not assignable to type 'string'

    // ✅ Using union type
    let name: string | null = null;
    name = "Alice";

    // ✅ Optional chaining
    interface User {
      email?: string;
    }

    function sendEmail(user: User) {
      // ❌ Error
      const length = user.email.length;
      //                  ^^^^^ Object is possibly 'undefined'

      // ✅ Optional chaining
      const length = user.email?.length;

      // ✅ Null check
      if (user.email !== undefined) {
        const length = user.email.length;
      }
    }
    ```

    **In Sonamu:**

    ```typescript theme={null}
    // Entity defined via entity.json
    interface User {
      id: number;
      name: string;           // Cannot be null
      bio: string | null;     // Allows null
      email?: string;         // Allows undefined
      created_at: Date;
    }

    // Ensure type safety in Model class
    class UserModelClass extends BaseModelClass {
      @api({ httpMethod: "GET" })
      async findById(
        subset: UserSubsetKey,
        id: number
      ): Promise<UserSubsetMapping[typeof subset] | null> {
        const rdb = this.getPuri("r");
        const user = await rdb.table("users").where("id", id).first();

        // strictNullChecks enforces null check
        if (!user) {
          return null;
        }

        return user;
      }
    }
    ```
  </Tab>

  <Tab title="strictFunctionTypes" icon="function">
    ### Strict Function Type Checking

    **Function:**

    * Checks contravariance of function parameters
    * Safer function type compatibility

    **Example:**

    ```typescript theme={null}
    interface Animal {
      name: string;
    }

    interface Dog extends Animal {
      bark(): void;
    }

    // ❌ Error (strictFunctionTypes: true)
    let animalHandler: (animal: Animal) => void;
    let dogHandler: (dog: Dog) => void;

    animalHandler = dogHandler;
    // ^^^^^^^^^ Type '(dog: Dog) => void' is not assignable to type '(animal: Animal) => void'

    // ✅ Correct direction
    dogHandler = animalHandler;  // OK
    ```

    <Info>
      This option significantly improves function type safety, but may have compatibility issues with some libraries.
    </Info>
  </Tab>

  <Tab title="strictBindCallApply" icon="link">
    ### Strict bind/call/apply Checking

    **Function:**

    * Type checks parameters of `bind`, `call`, `apply` methods

    **Example:**

    ```typescript theme={null}
    function greet(name: string, age: number) {
      console.log(`Hello, ${name}! You are ${age} years old.`);
    }

    // ❌ Error
    greet.call(null, "Alice", "30");
    //                        ^^^^ Argument of type 'string' is not assignable to parameter of type 'number'

    // ✅ Correct types
    greet.call(null, "Alice", 30);

    // ❌ Error
    greet.apply(null, ["Alice"]);
    //                ^^^^^^^^^ Argument of type '[string]' is not assignable to parameter of type '[string, number]'

    // ✅ Correct argument count
    greet.apply(null, ["Alice", 30]);
    ```
  </Tab>

  <Tab title="strictPropertyInitialization" icon="check-circle">
    ### Require Class Property Initialization

    **Function:**

    * Verifies that class properties are initialized in the constructor

    **Example:**

    ```typescript theme={null}
    class User {
      // ❌ Error
      name: string;
      // ^^^^ Property 'name' has no initializer and is not definitely assigned in the constructor

      // ✅ Initialized in constructor
      email: string;

      constructor(email: string) {
        this.email = email;
      }

      // ✅ Default value provided
      age: number = 0;

      // ✅ Optional
      bio?: string;

      // ✅ Allows null
      avatar: string | null = null;

      // ✅ Definite assignment assertion (only when certain)
      id!: number;
    }
    ```

    **In Sonamu:**

    ```typescript theme={null}
    // Generated types are all initialized
    interface UserRow {
      id: number;              // Auto-generated by DB
      email: string;           // Required field
      name: string;            // Default value "guest"
      created_at: Date;        // Default value CURRENT_TIMESTAMP
    }

    // Using Definite Assignment Assertion in Model class
    class UserModelClass extends BaseModelClass {
      // ! because initialized in constructor
      private readonly tableName!: string;

      constructor() {
        super();
        this.tableName = "users";
      }

      @api({ httpMethod: "POST" })
      async create(data: UserSaveParams) {
        // data must include required fields
        const wdb = this.getDB("w");
        return this.insert(wdb, data);
      }
    }
    ```
  </Tab>

  <Tab title="noImplicitThis" icon="cursor-arrow-rays">
    ### Require Explicit this Type

    **Function:**

    * Error when `this` type is unclear

    **Example:**

    ```typescript theme={null}
    // ❌ Error
    function onClick() {
      console.log(this.textContent);
      //          ^^^^ 'this' implicitly has type 'any'
    }

    // ✅ Explicit this type
    function onClick(this: HTMLElement) {
      console.log(this.textContent);
    }

    // ✅ Arrow function (no this binding)
    const onClick = () => {
      // Uses outer this
    };

    // ✅ Class method
    class Button {
      text: string = "Click me";

      onClick() {
        console.log(this.text);  // OK
      }
    }
    ```
  </Tab>
</Tabs>

## Additional Type Check Options

Sonamu enables additional check options beyond strict mode.

```json theme={null}
{
  "compilerOptions": {
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "useUnknownInCatchVariables": true,
    "noUncheckedIndexedAccess": true
  }
}
```

<Tabs>
  <Tab title="Unused Check" icon="trash">
    ### Warn About Unused Code

    ```json theme={null}
    {
      "noUnusedLocals": true,
      "noUnusedParameters": true
    }
    ```

    **Example:**

    ```typescript theme={null}
    // ❌ noUnusedLocals error
    function greet(name: string) {
      const message = "Hello";  // Unused
      //    ^^^^^^^ 'message' is declared but its value is never read
      return name;
    }

    // ❌ noUnusedParameters error
    function add(a: number, b: number) {
      //                     ^ 'b' is declared but its value is never read
      return a;
    }

    // ✅ Use _ to intentionally ignore
    function onClick(_event: MouseEvent) {
      console.log("Clicked!");
    }
    ```

    <Tip>
      Parameters starting with `_` don't trigger warnings.
    </Tip>
  </Tab>

  <Tab title="Return Check" icon="arrow-uturn-left">
    ### Require Return in All Code Paths

    ```json theme={null}
    {
      "noImplicitReturns": true
    }
    ```

    **Example:**

    ```typescript theme={null}
    // ❌ Error
    function getStatus(code: number): string {
      if (code === 200) {
        return "OK";
      } else if (code === 404) {
        return "Not Found";
      }
      // ^^^^ Not all code paths return a value
    }

    // ✅ Return in all paths
    function getStatus(code: number): string {
      if (code === 200) {
        return "OK";
      } else if (code === 404) {
        return "Not Found";
      }
      return "Unknown";
    }

    // ✅ Or explicit error
    function getStatus(code: number): string {
      if (code === 200) {
        return "OK";
      } else if (code === 404) {
        return "Not Found";
      }
      throw new Error(`Unknown status code: ${code}`);
    }
    ```
  </Tab>

  <Tab title="Switch Check" icon="list-bullet">
    ### Prevent Switch Statement Fallthrough

    ```json theme={null}
    {
      "noFallthroughCasesInSwitch": true
    }
    ```

    **Example:**

    ```typescript theme={null}
    // ❌ Error
    function getDay(day: number): string {
      switch (day) {
        case 0:
          return "Sunday";
        case 1:
          console.log("Monday");
          // ^^^^ Fallthrough case in switch
        case 2:
          return "Tuesday";
        default:
          return "Unknown";
      }
    }

    // ✅ Add break or return
    function getDay(day: number): string {
      switch (day) {
        case 0:
          return "Sunday";
        case 1:
          console.log("Monday");
          return "Monday";  // or break;
        case 2:
          return "Tuesday";
        default:
          return "Unknown";
      }
    }
    ```
  </Tab>

  <Tab title="Catch Variables" icon="exclamation-triangle">
    ### catch Block Variables are unknown

    ```json theme={null}
    {
      "useUnknownInCatchVariables": true
    }
    ```

    **Example:**

    ```typescript theme={null}
    try {
      throw new Error("Something went wrong");
    } catch (error) {
      // error is unknown type

      // ❌ Error
      console.log(error.message);
      //          ^^^^^ Object is of type 'unknown'

      // ✅ Use type guard
      if (error instanceof Error) {
        console.log(error.message);
      }

      // ✅ Type assertion (only when certain)
      const err = error as Error;
      console.log(err.message);
    }
    ```

    <Tip>
      Using `unknown` instead of `any` enforces type checking.
    </Tip>
  </Tab>

  <Tab title="Index Access" icon="hashtag">
    ### Require undefined Check for Array/Object Access

    ```json theme={null}
    {
      "noUncheckedIndexedAccess": true
    }
    ```

    **Example:**

    ```typescript theme={null}
    const users = ["Alice", "Bob"];

    // ❌ Error (noUncheckedIndexedAccess)
    const firstUser = users[0];
    //    ^^^^^^^^^ Type 'string | undefined'

    const name = firstUser.toUpperCase();
    //                     ^^^^^^^^^^^ Object is possibly 'undefined'

    // ✅ undefined check
    const firstUser = users[0];
    if (firstUser !== undefined) {
      const name = firstUser.toUpperCase();
    }

    // ✅ Optional chaining
    const name = users[0]?.toUpperCase();

    // ✅ Non-null assertion (only when certain)
    const name = users[0]!.toUpperCase();

    // Same for objects
    type UserMap = { [key: string]: string };
    const userMap: UserMap = { alice: "Alice" };

    const user = userMap["alice"];
    //    ^^^^ Type 'string | undefined'
    ```

    <Warning>
      This option makes all array/object access return `T | undefined`. May require many code changes.
    </Warning>
  </Tab>
</Tabs>

## Stricter Options (Optional)

Options you can add as needed.

```json theme={null}
{
  "compilerOptions": {
    "noPropertyAccessFromIndexSignature": true,
    "exactOptionalPropertyTypes": true,
    "noUncheckedSideEffectImports": true
  }
}
```

<Accordion title="noPropertyAccessFromIndexSignature" icon="key">
  **Index signatures can only be accessed with brackets**

  ```typescript theme={null}
  interface Options {
    [key: string]: string;
  }

  const options: Options = { color: "red" };

  // ❌ Error
  const color = options.color;

  // ✅ Use brackets
  const color = options["color"];
  ```

  **When to use:**

  * When you want to make dynamic property access explicit
</Accordion>

<Accordion title="exactOptionalPropertyTypes" icon="question-circle">
  **Optional properties only allow undefined**

  ```typescript theme={null}
  interface User {
    name?: string;
  }

  // ❌ Error
  const user: User = { name: undefined };

  // ✅ Omit property
  const user: User = {};

  // ✅ To explicitly allow undefined
  interface User {
    name: string | undefined;
  }
  ```

  **When to use:**

  * When you want to strictly distinguish between optional and `| undefined`

  <Warning>
    May have compatibility issues with many libraries.
  </Warning>
</Accordion>

## Disabling Type Checks

Sometimes you need to bypass type checks in specific situations.

<Tabs>
  <Tab title="Entire File" icon="file">
    ```typescript theme={null}
    // @ts-nocheck
    // Ignore all type checks in this file

    const value = "hello";
    value = 123;  // No error
    ```
  </Tab>

  <Tab title="Single Line" icon="minus">
    ```typescript theme={null}
    // @ts-ignore
    const value = someUntypedLibrary();

    // Or add error explanation
    // @ts-expect-error - External library type mismatch
    const value = someUntypedLibrary();
    ```

    <Tip>
      Use `@ts-expect-error` instead of `@ts-ignore` to get a warning when no error actually occurs.
    </Tip>
  </Tab>

  <Tab title="Type Assertion" icon="exclamation">
    ```typescript theme={null}
    // Type assertion with as
    const value = someValue as string;

    // Non-null assertion
    const element = document.getElementById("root")!;

    // Double assertion (last resort)
    const value = someValue as unknown as TargetType;
    ```

    <Danger>
      Type assertions break type safety. Use only when absolutely certain.
    </Danger>
  </Tab>
</Tabs>

## Recommended Settings

<Tabs>
  <Tab title="New Projects" icon="sparkles">
    ```json theme={null}
    {
      "compilerOptions": {
        // Use Sonamu default settings
        "strict": true,
        "noUnusedLocals": true,
        "noUnusedParameters": true,
        "noImplicitReturns": true,
        "noFallthroughCasesInSwitch": true,
        "useUnknownInCatchVariables": true,
        "noUncheckedIndexedAccess": true
      }
    }
    ```

    For new projects, **enable all options**.
  </Tab>

  <Tab title="Existing Projects" icon="arrow-path">
    ```json theme={null}
    {
      "compilerOptions": {
        "strict": true,
        // Add gradually
        // "noUnusedLocals": true,
        // "noUncheckedIndexedAccess": true
      }
    }
    ```

    For existing projects, **add options gradually**.

    **Recommended order:**

    1. `strict: true`
    2. `noUnusedLocals`, `noUnusedParameters`
    3. `noImplicitReturns`
    4. `noUncheckedIndexedAccess` (requires many changes)
  </Tab>

  <Tab title="Libraries" icon="cube">
    ```json theme={null}
    {
      "compilerOptions": {
        "strict": true,
        "declaration": true,
        "declarationMap": true,
        "noUnusedLocals": true,
        "noUnusedParameters": true
      }
    }
    ```

    For libraries, **type definition generation** is also essential.
  </Tab>
</Tabs>

## Performance Considerations

More type check options can increase compilation time.

<Accordion title="Improving Type Check Speed" icon="bolt">
  ```json theme={null}
  {
    "compilerOptions": {
      "skipLibCheck": true,           // Skip node_modules type check
      "incremental": true,             // Incremental compilation
      "tsBuildInfoFile": ".tsbuildinfo"
    }
  }
  ```

  **skipLibCheck**

  * Don't check `.d.ts` files in `node_modules`
  * Significantly reduces compilation time
  * Enabled by default in Sonamu

  **incremental**

  * Only recompile changed files
  * Cache stored in `.tsbuildinfo` file
</Accordion>

## Next Steps

<CardGroup cols={2}>
  <Card title="tsconfig.json" icon="file-code" href="/en/configuration/typescript/tsconfig">
    Check the complete TypeScript configuration
  </Card>

  <Card title="Path Mapping" icon="route" href="/en/configuration/typescript/path-mappings">
    Set up absolute path imports
  </Card>

  <Card title="Entity Definition" icon="database" href="/en/core-concepts/entity/defining-entities">
    Write type-safe Entities
  </Card>

  <Card title="Writing Tests" icon="flask" href="/en/testing/writing-tests/basic-testing">
    Write type-safe tests
  </Card>
</CardGroup>
