In TypeScript, intersections are used to combine multiple types into a single one. An intersection type is represented using the ampersand symbol &. It allows you to combine multiple types into a single type that includes all the properties and methods from each type, thus creating more flexible and powerful type definitions.
However, some of the basic types of TypeScript should not be used with intersections:
never type represents the type of values that never occur. Intersecting any type with never will always result in type never.any type allows to opt-out of type checking during compilation. Expressions of type any allow you to access arbitrary properties, even ones that don’t exist. any comes at the cost of losing type safety, which is one of the main motivations for using TypeScript. Avoid using any when not necessary. Intersecting any type with any will always result in type any.undefined and null types are the types for their respective value. Intersecting any type with them will always result in type never.void type implies the absence of a type. Intersecting any type with void will always result in type never.Additionally, an intersection with a type without members (for example, {}) doesn’t change the resulting type, is redundant, and can be safely removed from the intersection.
type Foo = T & null; // Noncompliant: 'Foo' is always 'never'
type Bar = T & any; // Noncompliant: 'Bar' is always 'any'
type Baz = T & U & {}; // Noncompliant: '{}' has no members and is redundant
Use consistent types that accurately reflect the domain of values of the defined data type.
type Foo = T | null; type Bar = T & U; type Baz = T & U;
No issue will be raised when & {} is used with generic type patterns where the empty type serves a legitimate purpose for type normalization or non-nullability constraints.
The following patterns are recognized:
{ [K in keyof T]: T[K] } & {} - Forces TypeScript to flatten or simplify complex type representations (Simplify/Prettify pattern)GenericType<T> & {} - Used for type normalization in complex generic type expressionsT & {} - Filters out null and undefined from type parameter TThese patterns are common TypeScript idioms for advanced type manipulation.
// Compliant by exception: Simplify/Prettify pattern forces type flattening
type Simplify<T> = { [K in keyof T]: T[K] } & {};
// Compliant by exception: Generic type normalization
interface SomeProps<T> { value: T; }
type ExtendedProps<T> = SomeProps<T> & {};
// Compliant by exception: Non-nullability constraint
type NonNullish<T> = T & {};
// Compliant by exception: Reversed order also works
type DeepPartialSet<T> = {} & Set<DeepPartial<T>>;
neveranynull and undefinedvoid