TS2322

React useState null vs undefined TS2322 fix in strict mode

Programming & Dev Tools Intermediate 👁 8 views 📅 Jun 18, 2026

TypeScript strict mode won't let you pass null to useState when the initial value is undefined. The fix is to set a proper initial value or widen the type.

Quick answer

Change your initial state to null or widen the type to string | null explicitly. The root cause: TypeScript's strict mode treats null and undefined as distinct types, and useState infers the type from the initial value.

What's actually happening here

You wrote something like:

const [value, setValue] = useState<string | undefined>(undefined);
// Later:
setValue(null); // TS2322: Argument of type 'null' is not assignable to parameter of type 'string | undefined'

The error pops up in React 18 with TypeScript 4.4+ and strict mode enabled. The reason step 3 works is that TypeScript infers the type of useState from its initial value. When you pass undefined, the inferred type becomes string | undefined. But null is not assignable to undefined — they're sibling types under the null and undefined types, not interchangeable.

This catches real bugs. Say you're building a dropdown that's initially unset (undefined) but later you want to clear it to null to distinguish "user hasn't touched it yet" from "user explicitly cleared it." TypeScript forces you to be explicit about which one you mean.

The error appears in real scenarios like: a search input that starts undefined but you want to reset it to null after a clear button click, or a user profile field that's undefined before loading but null after a failed fetch.

Fix steps

  1. Check your TypeScript config — open tsconfig.json and confirm strict: true or strictNullChecks: true is set. This is the default in modern Create React App and Vite setups.
  2. Identify the problematic useState — look for a call where the initial value is undefined but you're later setting null. Example: const [name, setName] = useState<string | undefined>(undefined).
  3. Change the initial value to null — this is the simplest fix if you don't care about the undefined vs null distinction. const [name, setName] = useState<string | null>(null). Now both null and string are valid, and you can pass null freely.
  4. Or widen the type union — if you need both null and undefined for semantic reasons, change the type to string | null | undefined: const [name, setName] = useState<string | null | undefined>(undefined). Now you can pass either null or undefined to setName.
  5. If you're migrating from non-strict code, you might need to update multiple calls. Search your codebase for useState.*undefined and check if any setState calls pass null. Fix all of them.

Alternative fixes if the main one fails

If you can't modify the initial value (say it comes from a library hook that returns undefined), use a type assertion:

setValue(null as string | null | undefined);

But I'd avoid that — it bypasses type checking and can hide real issues. A better escape hatch is to cast through unknown:

setValue((null as unknown) as string | undefined);

Even that's ugly. The real fix is to align your types properly.

If you're using useState with a complex object and you initialize it with undefined but later want null to mean "reset to empty," consider using a discriminated union or a separate boolean flag instead of mixing null and undefined.

Prevention tip

Stop treating null and undefined as the same thing. They're not. Pick one convention per project — I prefer null for "explicitly empty" and undefined for "not yet initialized." Then your types will be clean:

// If the value hasn't loaded yet:
const [user, setUser] = useState<User | undefined>(undefined);

// If the value can be empty after loading:
const [search, setSearch] = useState<string | null>(null);

This way you never need to mix them. When you fetch data, initialize with undefined (loading state), and after fetch, use null to represent "no data." TypeScript strict mode will thank you.

One more thing: if you're using useEffect to reset state, make sure your cleanup or effect doesn't set null where the initial state was undefined. Same error shows up there too.

Was this solution helpful?