Suggest an editImprove this articleRefine the answer for “Type inference with generics”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)When you call a function with a generic parameter, TypeScript **analyzes the arguments passed** and substitutes the type for `T` (or other parameters) itself, so you don't need to write `<string>`, `<number>`, and so on by hand. **Key point:** when TypeScript cannot infer the type precisely (for example, from `null`), the type must be specified explicitly.Shown above the full answer for quick recall.Answer (EN)Image## What type inference means in the context of generics When you call a function with a generic parameter, TypeScript **analyzes the arguments passed** and **substitutes the type itself** for `T` (or other parameters). That is, you don't need to explicitly write `<string>`, `<number>`, and so on - the compiler does this automatically. --- ### Example 1: basic type inference ```javascript function identity<T>(value: T): T { return value; } const a = identity("Hello"); // T = string const b = identity(42); // T = number ``` TypeScript sees that the argument `"Hello"` has type `string`, and substitutes `T = string` automatically. --- ### Example 2: inference from multiple arguments ```javascript function merge<T, U>(a: T, b: U): T & U { return Object.assign({}, a, b); } const result = merge({ name: "Tim" }, { age: 25 }); // TypeScript infers T = { name: string }, U = { age: number } // The result has type { name: string; age: number } ``` Here `T` and `U` are inferred **separately for each argument**. TypeScript combines them via `&`. --- ### Example 3: inference from context (contextual inference) ```javascript function wrap<T>(value: T): { data: T } { return { data: value }; } const wrapped = wrap({ id: 1, name: "Tim" }); // T = { id: number; name: string } ``` TypeScript "sees" the structure of the passed object and infers the exact type. --- ### Example 4: partial inference ```javascript function pair<T, U = string>(first: T, second?: U): [T, U] { return [first, second as U]; } const p1 = pair(1); // T = number, U = string (default) const p2 = pair(true, false); // T = boolean, U = boolean ``` You can set a **default type** for a generic parameter - it is then used when TypeScript cannot infer the type from the arguments. --- ### Example 5: type inference on a function's return value ```javascript function makeArray<T>(item: T, times: number): T[] { return Array(times).fill(item); } const arr = makeArray(5, 3); // T = number -> number[] ``` The type `T` is inferred from the first argument, `item`. --- ### Example 6: when inference does not work ```javascript function logValue<T>(value: T): void { console.log(value); } logValue(null); // T cannot be inferred precisely logValue(undefined); // the same applies ``` In such cases the type must be specified explicitly: ```javascript logValue<string | null>(null); ``` --- ## How inference works under the hood TypeScript applies several strategies: 1. **From arguments to type parameters** - analyzing the arguments and their types. 2. **From return type** - when the result type can be computed. 3. **Contextual typing** - analyzing the context in which the function is used. An example of contextual inference: ```javascript const handler = <T>(value: T) => console.log(value); ["a", "b", "c"].forEach(handler); // TypeScript understands that T = string ``` --- ## Summary | What TS does | Example | Result | |---|---|---| | Infers the type from an argument | `identity(42)` | `T = number` | | Infers the type from multiple arguments | `merge({a: 1}, {b: 2})` | `T = {a: number}, U = {b: number}` | | Applies the default type | `pair(1)` | `U = string` | | Contextual inference | `["x"].forEach(handler)` | `T = string` | | Cannot infer the type | `logValue(null)` | must be specified explicitly |For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.