fimbullinter / wotan

Pluggable TypeScript and JavaScript linter
Apache License 2.0
281 stars 23 forks source link

Add rule to detect redundant type arguments #326

Open ajafff opened 6 years ago

ajafff commented 6 years ago

When a type argument is the same type as the corresponding default of the type parameter, it can typically be omitted.

class MySet<T = any> extends Set<T> {}

var v: MySet<any>; // redundant
new MySet<any>(); // redundant

// if the contextual type has a different type argument, omitting the type argument changes the semantics

var myVar: MySet<string> = new MySet<any>([1, 2, 3]); // this is unsound, but sometimes necessary

// beware of type parameters
interface Base<T, U = T> {}
interface Child<T> extends Base<T, T> {} // the second type argument `T` is actually different from the default

A similar rule exists in TSLint as use-default-type-parameter

aervin commented 6 years ago

I frequently make mistakes like these. Would love to see a rule that checks for things like this. Feels "over my head" as far as rule implementations go. I'll see about helping out with some of the other issues though.

ajafff commented 6 years ago

This rule should also cover the following case where the contextual type provides the type arguments:

const m: Map<string, string> = new Map();

// here it's actually required (ts 2.9.1), without the type arguments `'foo' | 'bar'` is widened to `string`
const m: Map<string, 'foo' | 'bar'> = new Map<string, 'foo' | 'bar'>([['a', 'foo'], ['b', 'bar']]);

// the same also applies for type parameter defaults without contextual type
class MySet<T = 'foo'> extends Set<T> {}
const result = new MySet<'foo'>(['foo']); // type argument is necessary to avoid widening
ajafff commented 5 years ago

Note that for CallLikeExpressions type arguments may actually be required because they may otherwise be inferred differently.

declare function call<T = string | number>(param: T, cb: (param?: T) => void): void;
call<string | number>(1, (param = '1') => {}); // would fail without type argument