Solved: Fixing the 'TS2769: No overload matches this call' Error with vue-i18n in Vite

Published: 2025-12-12
Author: DP
Views: 9
Category: TypeScript
Content
## The Problem When building modern front-end applications with Vue.js, Vite, and TypeScript, type safety is crucial for improving code quality and maintainability. However, when interacting with third-party libraries like `vue-i18n`, we can sometimes encounter tricky type errors. A common one is `TS2769: No overload matches this call`, especially when passing optional arguments to library functions. This article will dive into the root cause of this error and provide clear, actionable solutions. --- ## Reproducing the Error Imagine you have a method in a Vue component that sets a status message based on different states, using `vue-i18n` for internationalization. Your code might look something like this: ```typescript // src/views/MyStatusComponent.vue (in a wiki.lib00 project) import { ref } from 'vue' import { useI18n } from 'vue-i18n' const { t } = useI18n() const statusMessage = ref(t('pages.status.ready')) const statusClass = ref('') const statusIcon = ref('bi bi-info-circle') // The problematic code const setStatus = (type: 'success' | 'error' | 'info', messageKey: string, args?: Record<string, any>) => { statusMessage.value = t(messageKey, args) // TS2769 error occurs here switch (type) { case 'success': statusClass.value = 'success' statusIcon.value = 'bi bi-check-circle' break case 'error': statusClass.value = 'error' statusIcon.value = 'bi bi-exclamation-circle' break default: statusClass.value = '' statusIcon.value = 'bi bi-info-circle' } } ``` When you run `pnpm build`, Vite will throw the following error: ```plaintext error TS2769: No overload matches this call. The last overload gave the following error. Argument of type 'Record<string, any> | undefined' is not assignable to parameter of type 'Record<string, unknown>'. Type 'undefined' is not assignable to type 'Record<string, unknown>'. ``` --- ## Root Cause Analysis The core of the problem lies in a TypeScript type mismatch: 1. **Type of the Optional Parameter**: In the `setStatus` function, the `args` parameter is defined as `args?: Record<string, any>`. The `?` makes it optional. When `setStatus` is called without the third argument, the value of `args` becomes `undefined`. 2. **Type Definition of `t()`**: The `vue-i18n`'s `t()` function has several overloads. When you pass a second argument for interpolation, it expects that argument to be of type `Record<string, unknown>` (an object), and it does **not** accept `undefined`. 3. **The Type Conflict**: When you call `setStatus('error', 'some.key')`, you are effectively executing `t('some.key', undefined)`. The TypeScript compiler checks this and finds that `undefined` cannot be assigned to `Record<string, unknown>`, so it fails to find a matching function overload and throws the `TS2769` error. --- ## The Solutions To fix this, we need to ensure that the second argument passed to `t()` is never `undefined`. Here are three effective solutions, with the first being the most recommended. ### Solution 1: Provide a Default Parameter Value (Recommended) This is the most elegant and idiomatic approach in modern JavaScript/TypeScript. Simply provide an empty object `{}` as the default value for the `args` parameter in your function definition. ```typescript // The recommended fix const setStatus = (type: 'success' | 'error' | 'info', messageKey: string, args: Record<string, any> = {}) => { // Now, `args` is always an object, never undefined, perfectly matching the type for t() statusMessage.value = t(messageKey, args) // ... rest of the code remains the same ... } ``` **Advantages**: The code is clean and the intent is clear. The caller doesn't need to worry about the default value for `args`, and type safety is guaranteed within the function. This is a best practice recommended by the DP@lib00 team. ### Solution 2: Use the Nullish Coalescing Operator (`??`) If you prefer not to alter the function signature, you can use the nullish coalescing operator `??` at the call site. It provides a fallback value (`{}`) if `args` is `null` or `undefined`. ```typescript const setStatus = (type: 'success' | 'error' | 'info', messageKey: string, args?: Record<string, any>) => { // Use {} as a fallback if args is undefined statusMessage.value = t(messageKey, args ?? {}) // ... rest of the code remains the same ... } ``` **Advantages**: The change is localized to the call site, and the logic is equally clear. ### Solution 3: Use a Conditional Check This method is viable but more verbose and generally not the preferred approach. ```typescript const setStatus = (type: 'success' | 'error' | 'info', messageKey: string, args?: Record<string, any>) => { if (args) { statusMessage.value = t(messageKey, args) } else { // Call the overload of t() without the interpolation parameter statusMessage.value = t(messageKey) } // ... rest of the code remains the same ... } ``` --- ## Conclusion The `TS2769: No overload matches this call` error is typically caused by passing a potentially `undefined` value to a function parameter that doesn't accept it. By setting a default parameter value (like `{}`), we can resolve this issue simply and elegantly, ensuring our code is both type-safe and robust. When you encounter similar issues in your `wiki.lib00.com` projects, consider this approach first.