Lint Rules

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> = {};