Skip to content

noRedundantTypeConstituents (JavaScript)

Language JavaScript (and super languages)
biome.json
{
"linter": {
"rules": {
"nursery": {
"noRedundantTypeConstituents": "error"
}
}
}
}

Disallow members of union and intersection types that have no effect.

A union type (A | B) accepts a value if it matches any of its members. An intersection type (A & B) accepts a value only if it matches all of its members. Some members make the others pointless, or are pointless themselves:

  • In a union, any and unknown accept every value, so the other members have no effect.
  • In a union, never accepts no value, so it has no effect. It’s allowed when the union is the return type of a function.
  • In a union, a literal type such as "a" or 1 has no effect when the union also includes its primitive type, such as string or number.
  • In an intersection, any and never replace the whole type, so the other members have no effect.
  • In an intersection, unknown has no effect.
  • In an intersection, a primitive type such as string has no effect when the intersection also includes one of its literal types, such as "a".

These members usually point to a mistake, such as a type that is wider than intended.

This rule only looks at the types written directly in the union or intersection. It doesn’t follow type aliases or other named types.

type UnionAny = any | "foo";
code-block.ts:1:17 lint/nursery/noRedundantTypeConstituents ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

⚠ The any type makes every other member of this union redundant.

> 1 │ type UnionAny = any | "foo";
│ ^^^
2 │

ℹ This union is always any, whatever its other members are.

ℹ If the type should be any, replace the whole union with any. Otherwise, remove any.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

type UnionUnknown = unknown | "foo";
code-block.ts:1:21 lint/nursery/noRedundantTypeConstituents ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

⚠ The unknown type makes every other member of this union redundant.

> 1 │ type UnionUnknown = unknown | "foo";
│ ^^^^^^^
2 │

ℹ This union is always unknown, whatever its other members are.

ℹ If the type should be unknown, replace the whole union with unknown. Otherwise, remove unknown.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

type UnionNever = never | "foo";
code-block.ts:1:19 lint/nursery/noRedundantTypeConstituents ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

⚠ The never type has no effect in this union.

> 1 │ type UnionNever = never | "foo";
│ ^^^^^
2 │

ℹ This union accepts the same values with or without never.

ℹ Remove never.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

type UnionBooleanLiteral = boolean | false;
code-block.ts:1:38 lint/nursery/noRedundantTypeConstituents ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

⚠ This literal type is redundant because the union also includes boolean.

> 1 │ type UnionBooleanLiteral = boolean | false;
│ ^^^^^
2 │

ℹ Every value of this literal type is already a boolean, so the union accepts the same values without it.

ℹ Remove the literal type, or remove boolean if only specific values should be accepted.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

type UnionNumberLiteral = number | 1;
code-block.ts:1:36 lint/nursery/noRedundantTypeConstituents ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

⚠ This literal type is redundant because the union also includes number.

> 1 │ type UnionNumberLiteral = number | 1;
│ ^
2 │

ℹ Every value of this literal type is already a number, so the union accepts the same values without it.

ℹ Remove the literal type, or remove number if only specific values should be accepted.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

type UnionStringLiteral = string | "foo";
code-block.ts:1:36 lint/nursery/noRedundantTypeConstituents ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

⚠ This literal type is redundant because the union also includes string.

> 1 │ type UnionStringLiteral = string | "foo";
│ ^^^^^
2 │

ℹ Every value of this literal type is already a string, so the union accepts the same values without it.

ℹ Remove the literal type, or remove string if only specific values should be accepted.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

type IntersectionAny = any & "foo";
code-block.ts:1:24 lint/nursery/noRedundantTypeConstituents ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

⚠ The any type makes every other member of this intersection redundant.

> 1 │ type IntersectionAny = any & "foo";
│ ^^^
2 │

ℹ This intersection is always any, whatever its other members are.

ℹ If the type should be any, replace the whole intersection with any. Otherwise, remove any.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

type IntersectionUnknown = string & unknown;
code-block.ts:1:37 lint/nursery/noRedundantTypeConstituents ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

⚠ The unknown type has no effect in this intersection.

> 1 │ type IntersectionUnknown = string & unknown;
│ ^^^^^^^
2 │

ℹ This intersection accepts the same values with or without unknown.

ℹ Remove unknown.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

type IntersectionNever = string & never;
code-block.ts:1:35 lint/nursery/noRedundantTypeConstituents ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

⚠ The never type makes every other member of this intersection redundant.

> 1 │ type IntersectionNever = string & never;
│ ^^^^^
2 │

ℹ This intersection is always never, whatever its other members are.

ℹ If the type should be never, replace the whole intersection with never. Otherwise, remove never.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

type IntersectionBooleanLiteral = boolean & false;
code-block.ts:1:35 lint/nursery/noRedundantTypeConstituents ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

⚠ The boolean type is redundant because the intersection also includes a boolean literal type.

> 1 │ type IntersectionBooleanLiteral = boolean & false;
│ ^^^^^^^
2 │

ℹ The literal type already limits the values to specific boolean values, so boolean doesn't change the result.

ℹ Remove boolean.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

type IntersectionNumberLiteral = number & 1;
code-block.ts:1:34 lint/nursery/noRedundantTypeConstituents ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

⚠ The number type is redundant because the intersection also includes a number literal type.

> 1 │ type IntersectionNumberLiteral = number & 1;
│ ^^^^^^
2 │

ℹ The literal type already limits the values to specific number values, so number doesn't change the result.

ℹ Remove number.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

type IntersectionStringLiteral = string & "foo";
code-block.ts:1:34 lint/nursery/noRedundantTypeConstituents ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

⚠ The string type is redundant because the intersection also includes a string literal type.

> 1 │ type IntersectionStringLiteral = string & "foo";
│ ^^^^^^
2 │

ℹ The literal type already limits the values to specific string values, so string doesn't change the result.

ℹ Remove string.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

type UnionAny = any;
type UnionUnknown = unknown;
type UnionNever = never;
type UnionBooleanLiteral = boolean;
type UnionNumberLiteral = number;
type UnionStringLiteral = string;
type IntersectionAny = any;
type IntersectionUnknown = string;
type IntersectionNever = never;
type IntersectionBooleanLiteral = false;
type IntersectionNumberLiteral = 1;
type IntersectionStringLiteral = "foo";
declare function fail(): string | never;