Type inference lets TypeScript determine types from values and surrounding declarations without annotating every variable. Given `function fibonacci(a: number, b: number) { return a + b; }`, it infers a `number` return value. Variables initialized with numbers, and variables assigned the function’s result, need no separate annotations. The parameter annotations matter: without them, the checker lacks the information needed to reject unsuitable arguments. section 5.2.2
Inference follows the value supplied to a React hook, not every value the component might need later. `useState(null)` produces state typed as `null`, so `setIsAccepted(true)` fails. If an appointment response starts undecided but can become accepted or rejected, declare that range: `useState<null | boolean>(null)`. Likewise, an empty array does not tell TypeScript that future entries will be strings; use `useState<string[]>([])` for a tag list. Prefer these type arguments when an initializer cannot express the intended state. section 6.1.1
Context has the same boundary. `createContext(false)` infers a Boolean context, and `useContext` returns the context’s type without another hint. If a context starts at `null` but providers supply an object containing a mode and a toggle function, define that shape and pass `DarkMode | null` to `createContext`. A wrapper hook can check for a missing provider before returning the value. section 6.1.3
Generic functions can infer a type argument from their value arguments. For `getMiddle<Type>(list: Type[]): Type`, a number array yields a number result and a string array yields a string result. Supplying a broader argument such as `number | string` explicitly also broadens the return type; specify it only when that trade-off is useful. section 5.3.1
Contextual inference depends on where a callback is written. An inline playlist callback receives parameter types from the receiving component’s prop. Moving that callback into `useCallback` removes that immediate context, so its parameters need types supplied at the function, through a `useCallback` type argument, or on the target variable. Inference reduces annotation work, but moving code can change what the checker knows. section 6.1.6
// Define the function arguments in the function definition
const handleMove = useCallback(
(index: number) => (evt: MouseEvent<HTMLButtonElement>) => {
const type = evt.currentTarget.name as ActionType;
dispatch({ type, index });
},
[dispatch]
);
// Define the function type generally as a type argument to useCallback
const handleMove = useCallback<
(index: number) => (evt: MouseEvent<HTMLButtonElement>) => void
>(
(index) => (evt) => {
const type = evt.currentTarget.name as ActionType;
dispatch({ type, index });
},
[dispatch]
);
// Defines the function type on the target variable
const handleMove: (
index: number
) => (evt: MouseEvent<HTMLButtonElement>) => void = useCallback(
(index) => (evt) => {
const type = evt.currentTarget.name as ActionType;
dispatch({ type, index });
},
[dispatch]
);
Compare three ways to type the same memoized callback when its parameters can no longer be inferred from the component prop. section 6.1.6















