noUselessTypeConstraint (since vnext)
This rule is recommended by Rome.
Disallow using any
or unknown
as type constraint.
Generic type parameters (<T>
) in TypeScript may be constrained with extends
. A supplied type must then be a subtype of the supplied constraint. All types are subtypes of any
and unknown
. It is thus useless to extend from any
or unknown
.
Source: https://typescript-eslint.io/rules/no-unnecessary-type-constraint/
Examples
Invalid
interface FooAny<T extends any> {}
complexity/noUselessTypeConstraint.js:1:20 lint/complexity/noUselessTypeConstraint FIXABLE ━━━━━━━━━━
✖ Constraining a type parameter to any or unknown is useless.
> 1 │ interface FooAny<T extends any> {}
│ ^^^^^^^^^^^
2 │
ℹ All types are subtypes of any and unknown.
ℹ Suggested fix: Remove the constraint.
1 │ interface·FooAny<T·extends·any>·{}
│ -----------
type BarAny<T extends any> = {};
complexity/noUselessTypeConstraint.js:1:15 lint/complexity/noUselessTypeConstraint FIXABLE ━━━━━━━━━━
✖ Constraining a type parameter to any or unknown is useless.
> 1 │ type BarAny<T extends any> = {};
│ ^^^^^^^^^^^
2 │
ℹ All types are subtypes of any and unknown.
ℹ Suggested fix: Remove the constraint.
1 │ type·BarAny<T·extends·any>·=·{};
│ -----------
class BazAny<T extends any> {
}
complexity/noUselessTypeConstraint.js:1:16 lint/complexity/noUselessTypeConstraint FIXABLE ━━━━━━━━━━
✖ Constraining a type parameter to any or unknown is useless.
> 1 │ class BazAny<T extends any> {
│ ^^^^^^^^^^^
2 │ }
3 │
ℹ All types are subtypes of any and unknown.
ℹ Suggested fix: Remove the constraint.
1 │ class·BazAny<T·extends·any>·{
│ -----------
class BazAny {
quxAny<U extends any>() {}
}
complexity/noUselessTypeConstraint.js:2:12 lint/complexity/noUselessTypeConstraint FIXABLE ━━━━━━━━━━
✖ Constraining a type parameter to any or unknown is useless.
1 │ class BazAny {
> 2 │ quxAny<U extends any>() {}
│ ^^^^^^^^^^^
3 │ }
4 │
ℹ All types are subtypes of any and unknown.
ℹ Suggested fix: Remove the constraint.
2 │ ··quxAny<U·extends·any>()·{}
│ -----------
const QuuxAny = <T extends any>() => {};
complexity/noUselessTypeConstraint.js:1:20 lint/complexity/noUselessTypeConstraint FIXABLE ━━━━━━━━━━
✖ Constraining a type parameter to any or unknown is useless.
> 1 │ const QuuxAny = <T extends any>() => {};
│ ^^^^^^^^^^^
2 │
ℹ All types are subtypes of any and unknown.
ℹ Suggested fix: Remove the constraint.
1 │ const·QuuxAny·=·<T·extends·any>()·=>·{};
│ -----------
function QuuzAny<T extends any>() {}
complexity/noUselessTypeConstraint.js:1:20 lint/complexity/noUselessTypeConstraint FIXABLE ━━━━━━━━━━
✖ Constraining a type parameter to any or unknown is useless.
> 1 │ function QuuzAny<T extends any>() {}
│ ^^^^^^^^^^^
2 │
ℹ All types are subtypes of any and unknown.
ℹ Suggested fix: Remove the constraint.
1 │ function·QuuzAny<T·extends·any>()·{}
│ -----------
interface FooUnknown<T extends unknown> {}
complexity/noUselessTypeConstraint.js:1:24 lint/complexity/noUselessTypeConstraint FIXABLE ━━━━━━━━━━
✖ Constraining a type parameter to any or unknown is useless.
> 1 │ interface FooUnknown<T extends unknown> {}
│ ^^^^^^^^^^^^^^^
2 │
ℹ All types are subtypes of any and unknown.
ℹ Suggested fix: Remove the constraint.
1 │ interface·FooUnknown<T·extends·unknown>·{}
│ ---------------
type BarUnknown<T extends unknown> = {};
complexity/noUselessTypeConstraint.js:1:19 lint/complexity/noUselessTypeConstraint FIXABLE ━━━━━━━━━━
✖ Constraining a type parameter to any or unknown is useless.
> 1 │ type BarUnknown<T extends unknown> = {};
│ ^^^^^^^^^^^^^^^
2 │
ℹ All types are subtypes of any and unknown.
ℹ Suggested fix: Remove the constraint.
1 │ type·BarUnknown<T·extends·unknown>·=·{};
│ ---------------
class BazUnknown<T extends unknown> {
}
```ts,expect_diagnostic
class BazUnknown {
quxUnknown<U extends unknown>() {}
}
complexity/noUselessTypeConstraint.js:3:4 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✖ unterminated template literal
1 │ class BazUnknown<T extends unknown> {
2 │ }
> 3 │ ```ts,expect_diagnostic
│ ^^^^^^^^^^^^^^^^^^^^
> 4 │ class BazUnknown {
> 5 │ quxUnknown<U extends unknown>() {}
> 6 │ }
> 7 │
│
const QuuxUnknown = <T extends unknown>() => {};
complexity/noUselessTypeConstraint.js:1:24 lint/complexity/noUselessTypeConstraint FIXABLE ━━━━━━━━━━
✖ Constraining a type parameter to any or unknown is useless.
> 1 │ const QuuxUnknown = <T extends unknown>() => {};
│ ^^^^^^^^^^^^^^^
2 │
ℹ All types are subtypes of any and unknown.
ℹ Suggested fix: Remove the constraint.
1 │ const·QuuxUnknown·=·<T·extends·unknown>()·=>·{};
│ ---------------
function QuuzUnknown<T extends unknown>() {}
complexity/noUselessTypeConstraint.js:1:24 lint/complexity/noUselessTypeConstraint FIXABLE ━━━━━━━━━━
✖ Constraining a type parameter to any or unknown is useless.
> 1 │ function QuuzUnknown<T extends unknown>() {}
│ ^^^^^^^^^^^^^^^
2 │
ℹ All types are subtypes of any and unknown.
ℹ Suggested fix: Remove the constraint.
1 │ function·QuuzUnknown<T·extends·unknown>()·{}
│ ---------------
Valid
interface Foo<T> {}
type Bar<T> = {};