This document covers breaking changes introduced across TypeScript 4.0 through 4.9 that are likely to surface during a routine upgrade. These accumulate — upgrading from 4.0 to 5.0 means encountering all of them.

# TypeScript 4.x Changes

## `any`/`unknown` propagated in falsy positions

Previously `foo && somethingElse` where `foo` is `any`/`unknown` returned the type of `somethingElse`. Now it propagates `any`/`unknown`.

```diff
- // x was { someProp: string }
+ // x is now 'unknown'
  let x = foo && somethingElse;
```

Fix: use `!!foo && someExpression` instead of `foo && someExpression`.

## Type parameter no longer optional in `Promise`:**

```diff
- new Promise(resolve => { resolve(); })
+ new Promise<void>(resolve => { resolve(); })
```

If `resolve()` is called without arguments, give `Promise` an explicit `void` type argument.

## Conditional spreads create optional properties

Object spreads like `{ ...(pet?.owner) }` now produce optional properties instead of a union type. This may cause type mismatches downstream. Correct fix is context-dependent.

## The `in` operator no longer allows primitive types on the right side

```ts
"foo" in 42 // Now an error
```
This is always a usercode bug.

## `.d.ts` extensions cannot be used in import paths:**

```diff
- import { Foo } from "./foo.d.ts";
+ import { Foo } from "./foo";
```
Remove the `.d.ts` suffix, replacing with `.js` if in a module mode that uses extensions.

## Always-truthy Promise checks (under `strictNullChecks`)

```ts
declare var p: Promise<number>;
if (p) { } // Error! Did you forget to use 'await'?
```
This is always a usercode bug.

## Union enums cannot be compared to arbitrary numbers

```ts
enum E { A = 0, B = 1 }
function f(x: E) {
  if (x === -1) { } // Error! 'E' and '-1' have no overlap
}
```

Fix: use a type assertion `(x as number) === -1`, or this may be a usercode bug.

## `useUnknownInCatchVariables` enabled under `--strict`

Catch variables are now `unknown` instead of `any` when using `--strict`.

If the project has many errors as a result of this, turn off `useUnknownInCatchVariables`, otherwise add a `: any` (or e.g. `: Error`) type annotation where needed

## Inference changes from `Awaited` type

`Promise.all`, `Promise.race`, etc. now use the `Awaited` utility type. Explicit type arguments to these functions may need updating:

```diff
- Promise.all<boolean, boolean>(...)
+ Promise.all(...)
```

Or use tuple type arguments:

```diff
- Promise.all<boolean, boolean>(...)
+ Promise.all<[boolean, boolean]>(...)
```

## Compiler options checking at root of `tsconfig.json`

It is now an error to add compiler option fields at the top level of `tsconfig.json` without a `compilerOptions` wrapper.
This is always a user misconfiguration, ask them what they meant to do.


## Stricter checks with template string expressions

Using a value constrained to `string | symbol` in a template string now errors:

```ts
function get<T, K extends keyof T>(obj: T, key: K) {
  console.log(`${key}`); // Error if K could be symbol
}
```
If you can't fix this by changing the constraint to `string & keyof T`, then this is a usercode bug.

## Unconstrained generics no longer assignable to `{}`

Under `strictNullChecks`, an unconstrained type parameter `T` cannot be assigned where `null`/`undefined` are not legal:

```ts
function foo<T>(x: T) {
  needsNotNullValue(x); // Error! T is not assignable to {}
}
```

Fix: add a constraint `<T extends {}>` (preferred), check for null/undefined at runtime, or use a non-null assertion.

# TypeScript 5.0 Specific Changes

## Decorators are now stage 3 standard

Legacy experimental decorators (`experimentalDecorators`) still work but the new decorator semantics are the default. Code using decorators may need adjustments if it was relying on the old metadata/parameter decorator behavior. You (the AI agent) will not be able to fix these; defer to the user if you think this is relevant.

## Removed compiler options/values

- `charset` - just remove, no one uses this anymore
- `target: ES3` - change to `ES5`
- `importsNotUsedAsValues` - remove
- `noImplicitUseStrict` - remove, this is no longer meaningful
- `noStrictGenericChecks` - remove and add type parameters where needed
- `keyofStringsOnly` - remove, use `string & keyof T` in lieu of `keyof T` where needed
- `suppressExcessPropertyErrors` - remove, use documented workarounds
- `suppressImplicitAnyIndexErrors` - remove, use documented workarounds
- `out` - change to `outFile`
- `preserveValueImports` - remove, use `verbatimModuleSyntax` instead *once you are on TS 6.0*
- `prepend` in project references - abort and tell the user they need to set up a bundler themselves
