liveBook · Manning

Type inference

As explained in React in Depth

Type inference is the compiler's determination of a type from available values, expressions, or contextual constraints without an explicit type annotation.

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

How React in Depth covers it

How deep it goes
Works through inferred results, generic arguments, state, context, and callback placement; does not explain compiler internals.
Examples
Uses a Fibonacci function, an appointment response, a tag form, dark-mode context, and playlist callbacks.
What it assumes
Assumes familiarity with React hooks while introducing TypeScript parameter annotations through a small function.
What you can do after
Apply it via TypeScript type arguments and annotations when React initializers or callback placement leave intended types unclear.
How it connects
Connects type inference to static typing, generic functions, React state, context, and memoized callbacks.

Also explained in

Compare how 16 books explain type inference →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of React in Depth. The section links point to the parts of the book it draws on.