TypeScript + ESLint
- Require that member overloads be consecutive
- Requires using either
T[]
orArray<T>
for arrays - Disallows awaiting a value that is not a Thenable
- Requires type annotations to exist (typedef)
- Require explicit return and argument types on exported functions' and classes' public class methods
Use
'@typescript-eslint/adjacent-overload-signatures': 'error'
,
because grouping overloaded members together can improve readability of the code.
class Foo {
foo(s: string): void;
foo(n: number): void;
bar(): void {}
foo(sn: string | number): void {}
}
export function foo(s: string): void;
export function foo(n: number): void;
export function bar(): void;
export function foo(sn: string | number): void;
class Foo {
foo(s: string): void;
foo(n: number): void;
foo(sn: string | number): void {}
bar(): void {}
}
export function bar(): void;
export function foo(s: string): void;
export function foo(n: number): void;
export function foo(sn: string | number): void;
Use
'@typescript-eslint/array-type': 'error'
for always using T[]
or readonly T[]
for all array types.
const x: Array<string> = ['a', 'b'];
const y: ReadonlyArray<string> = ['a', 'b'];
const x: string[] = ['a', 'b'];
const y: readonly string[] = ['a', 'b'];
Use
'@typescript-eslint/await-thenable': 'error'
await 'value';
const createValue = () => 'value';
await createValue();
await Promise.resolve('value');
const createValue = async () => 'value';
await createValue();
Many believe that requiring type annotations unnecessarily can be cumbersome to maintain and generally reduces code
readability. TypeScript is often better at inferring types than easily written type annotations would allow. And many
people believe instead of enabling typedef, it is generally recommended using the --noImplicitAny
and
--strictPropertyInitialization
compiler options to enforce type annotations only when useful. This rule can enforce
type annotations in locations regardless of whether they're required.
But why is annotation description useful? Because for the code review, you will not be able to find out what will change in runtime due to inferred types. But when you specify types, you know exactly what to change to:
It is also worth noting that if we do not use type annotations for methods, it may be difficult for us to read the code during the review, we may not notice something and not pay attention to how the data type has changed if the build does not crash with an error.
Reference to explicit-module-boundary-types
Explicit types for function return values and arguments makes it clear to any calling code what is the module boundary's input and output.
// Should indicate that a number is returned
export function myFn() {
return 1;
}
// A return value of type number
export function myFn(): number {
return 1;
}