# `deslop/redundant-type-pattern`

Disallow redundant type expressions with a no-op operand, e.g. `T & {}`, `Partial<Partial<T>>`, `Pick<X, keyof X>`.

- **Category:** Architecture
- **Severity:** warn
- **Source:** deslop-js
- **Framework:** global
- **Enabled when:** react-doctor deadCode analysis enabled (default true); whole-project scan only — skipped in --diff/--staged modes
- **Documentation:** <https://github.com/millionco/deslop-js>

## Validation prompt

Use this to decide whether a fired diagnostic is real or a false positive.

Fires (always confidence "high", skipping .d.ts files) when deslop's detectRedundantTypePatterns finds a type expression whose operand is a no-op, tagged by kind: intersection-with-empty-object ("intersection with `{}` is a no-op; the empty object type does not constrain anything"), self-union ("union contains the same member twice") and self-intersection ("intersection contains the same operand twice") from a literally-equal duplicated member, nested-partial/nested-readonly/nested-required ("Partial<Partial<T>> collapses to Partial<T>", etc.), pick-all-keys ("Pick<X, keyof X> is equivalent to X itself"), omit-no-keys ("Omit<X, never> is equivalent to X itself"), or empty-interface-extends-one ("interface X extends Base with no new members"). False positive to SUPPRESS: an empty-interface-extends-one kept on purpose as a nominal branding marker or as a public declaration-merging / module-augmentation extension point that downstream code adds members to (the detector already excludes zod `.infer` and radix `.Props` aliases, so a remaining one is usually a deliberate seam); also leave `T & {}` if it is the intentional "force-simplify display" trick on a generic where you actually rely on the prettified hover type.

## Fix prompt

Use this once validation confirms the diagnostic is real.

Apply deslop's per-kind suggestion, which is the simplification itself: for intersection-with-empty-object drop the `& {}` term (`type A = B & {}` becomes `type A = B`); for self-union/self-intersection delete the duplicated member (`A | A` becomes `A`); for nested-partial/readonly/required flatten the wrapper (`Partial<Partial<T>>` becomes `Partial<T>`); for pick-all-keys replace `Pick<X, keyof X>` with `X` and for omit-no-keys replace `Omit<X, never>` with `X`; for empty-interface-extends-one rewrite `interface X extends Base {}` as `type X = Base` unless you are intentionally keeping a branding or declaration-merging seam, in which case leave it and document the intent. These collapse to the identical type, so removing the no-op operand reduces noise without changing behavior. See https://www.typescriptlang.org/docs/handbook/utility-types.html
