Skip to content

Latest commit

 

History

History
1317 lines (911 loc) · 21.8 KB

typescript.md

File metadata and controls

1317 lines (911 loc) · 21.8 KB

Typescript

Require that member overloads be consecutive (adjacent-overload-signatures from TSLint)

✅ Enabled (error)

// Bad
/*
interface IFoo {
	foo(s: string): void;
	foo(n: number): void;
	bar(): void;
	foo(sn: string | number): void;
}
*/
// Good
interface IFoo {
	foo(sn: string | number): void;
	foo(s: string): void;
	foo(n: number): void;
	bar(): void;
}

Requires using either T[] or Array for arrays (array-type)

✅ Enabled (error)

// Bad
/*
(async () => {
	type A = Array<string>;
})();
*/
// Good
(async () => {
	type A = string[];
})();

Bans // @ts- comments from being used or requires descriptions after directive (ban-ts-comment)

✅ Enabled (error)

// Bad
/*
(() => {
	if (false) {
		// @ts-expect-error
		console.log('hello');
		// @ts-ignore
		console.log('hello');
		// @ts-nocheck
		console.log('hello');
		// @ts-check
		console.log('hello');
	}
})();
*/

Enforces that types will not to be used (ban-types)

✅ Enabled (error)

// Bad
/*
(() => {
	const a: String = 'a';
	const b: Number = 1;
})();
*/
// Good
(() => {
	const a: string = 'a';
	const b: number = 1;
})();

Enforces consistent usage of type assertions. (consistent-type-assertions)

✅ Enabled (error)

// Bad
/* 
(() => {
	type Foo2 = object;
	const foo = <Foo2>{};
	const x = { text: true } as Foo2;
})();
*/

// Good
(() => {
	type T = object;
	type Foo = object;
	const data = { test: true };
	const x: T = { ...data };
	const y = { ...data } as any;
	const z = { ...data } as unknown;
	function foo(some: T) { throw { bar: 5 } as Foo; }
	foo({ ...data } as T);
})();

Require explicit return types on functions and class methods (explicit-function-return-type)

❌ Disabled

// Good
// Should indicate that no value is returned (void)
function test() {
	return;
}

// Should indicate that a number is returned
const fn = function () {
	return 1;
};

// Should indicate that a string is returned
const arrowFn = () => 'test';

class Test {
	// Should indicate that no value is returned (void)
	public method() {
		return;
	}
}

Require explicit return types on functions and class methods (explicit-function-return-type)

✅ Enabled (error)

// Bad
/*
class Animal {
	constructor(name) {
		this.animalName = name;
	}
	animalName: string;
	get name(): string {
		return this.animalName;
	}
	set name(value: string) {
		this.animalName = value;
	}
	walk() {
		// method
	}
}
*/
// Good
class Animal {
	private _animalName: string;
	public constructor(name: string) {
		this._animalName = name;
	}
	public get name(): string {
		return this._animalName;
	}
	public set name(value: string) {
		this._animalName = value;
	}
	public walk() {
		// method
	}
}

Enforces naming of generic type variables (generic-type-naming)

✅ Enabled (error)

// Bad
/*
(() => {
	type ReadOnly<SomeType extends object> = {
		readonly [TKey in keyof SomeType]: SomeType[TKey]
	};
})();
*/
// Good
(() => {
	type IReadOnly<TSomeType extends object> = {
		readonly [TKey in keyof TSomeType]: TSomeType[TKey]
	};
})();

Enforce consistent indentation (indent)

✅ Enabled (error)

// Bad
/*
type ReadOnly<SomeType extends object> = {
	readonly [TKey in keyof SomeType]: SomeType[TKey]
};
*/
// Good
type ReadOnly<TSomeType extends object> = {
	readonly [TKey in keyof TSomeType]: TSomeType[TKey]
};

Require that interface names be prefixed with I (interface-name-prefix)

✅ Enabled (error)

// Bad
/*
interface Animal {
	name: string;
}
*/
// Good
interface IAnimal {
	name: string;
}

Require a specific member delimiter style for interfaces and type literals (member-delimiter-style)

✅ Enabled (error)

// Bad
/*
interface IFoo {
	name: string,
	greet(): void,
}
*/
// Good
interface IFoo {
	name: string;
	greet(): void;
}

Require a consistent member declaration order (member-ordering)

✅ Enabled (error)

// Bad
/*
class Foo {
	private _c: string; // -> field
	protected static e: string; // -> field
	public d: string; // -> field

	public static a(): void {} // -> method
	public b(): void {} // -> method

	public constructor() {
		console.log('constructor');
	} // -> constructor
}
*/
// Good
class Foo {
	protected static e: string; // -> field
	public d: string; // -> field
	private _c: string; // -> field

	public constructor() {
		console.log('constructor');
	} // -> constructor

	public static a(): void {} // -> method
	public b(): void {} // -> method
}

Enforces naming conventions for everything across a codebase (naming-convention)

✅ Enabled (error)

// Bad
/*
import { no_camelcased } from 'eslint';

(() => {
	no_camelcased();
	// default
	const my_favorite_color = '#112C85';

	// variable
	const my_var = '';
	const MyVar = '';

	// class
	class invalidClassName {}
	class Another_Invalid_Class_Name {}
	const bar = class invalidName {};

	// interface
	interface someInterface {}

	// typeAlias
	type MyType = string;

	// member naming
	class HappyClass {
		private foo: string;
		private bar = 123;
		public _fizz() {}
	}

	// method
	class A {
		public constructor() {
			this.doSomething();
		}
		public _s() {
			document.write('something');
		}
		private doSomething() {
			document.write('something');
		}
	}

	// enum
	enum myEnum {
		a = 'a',
		b = 'b',
	}
})();
*/

// Good
import { no_camelcased as noCamelcased } from 'eslint';

(() => {
	noCamelcased();
	// default
	const myFavoriteColor = '#112C85';

	// variable
	const myVar = '';
	const MY_VAR = '';
	const _this = this;

	// class
	class ValidClassName {}
	class AnotherValidClassName {}
	const bar = class ValidName {};

	// interface
	interface ISomeInterface {}

	// typeAlias
	type TMyType = string;
	type IMyType = string;

	// member naming
	class HappyClass {
		private _foo: string;
		private _bar = 123;
		public fizz() {}
	}

	// method
	class A {
		public constructor() {
			this._doSomething();
		}
		public s() {
			document.write('something');
		}
		private _doSomething() {
			document.write('something');
		}
	}

	// enum
	enum MY_ENUM {
		a = 'a',
		b = 'b',
	}
	enum MyEnum {
		a = 'a',
		b = 'b',
	}

	type TReadOnly<TSomeType extends string> = { readonly [TKey in keyof TSomeType]: TSomeType[TKey] };

	// they should be okay
	const ERROR_CODES = {
		INVALID_USER_INPUT: 'INVALID_USER_INPUT',
		INVALID_SESSION_ID: 'INVALID_SESSION_ID',
		INTERNAL_SERVER_ERROR: 'INTERNAL_SERVER_ERROR',
	};

	function mockWriteFile() {
		return (_filePath: string, _data: unknown, onWrote: () => void) => {
			onWrote();
		};
	}

	const mockAuth = {
		access_token: 'authToken',
		signature: 'signature',
		Authorization: ({ accessToken }) => `Bearer ${accessToken}`,
	};

	const Component = () => {};
})();

Disallow generic Array constructors (no-array-constructor)

✅ Enabled (error)

// Bad
/*
(async () => {
	const arr1 = Array<number>(0, 1, 2);
	const arr2 = new Array<number>(0, 1, 2);

	const arr1 = Array(0, 1, 2);
	const arr2 = new Array(0, 1, 2);
})();
*/

// Good
(async () => {
	const arr3 = Array(500);
	const arr4 = new Array(3);
})();

Disallow the declaration of empty interfaces (no-empty-interface)

✅ Enabled (error)

// Bad
/*
(async () => {
	// an empty interface
	interface IFoo {}

	// an interface with only one supertype (Bar === Foo)
	interface IBar extends IFoo {}

	// an interface with an empty list of supertypes
	interface IBaz {}
})();
*/
// Good
(async () => {
	interface IFoo {
		name: string;
	}
	interface IBar extends IFoo {
		email: string;
	}
	interface IBaz {
		name: string;
	}
})();

Disallow usage of the any type (no-explicit-any)

❌ Disabled

// Bad

/*
const age: any = 'seventeen';
*/
// Good
// not that good but okay in this configuration
const age: any = 'seventeen';

Forbids the use of classes as namespaces (no-extraneous-class)

✅ Enabled (error)

// Bad
/*
class ConstructorOnly {
	public constructor() {
		console.log('constructor');
	}
}
*/
// Good
class ConstructorOnly {
	private _version: string = '1.1.0'
	public constructor() {
		console.log(`constructor ${this._version}`);
	}
}

Disallow iterating over an array with a for-in loop (no-for-in-array)

✅ Enabled (error)

// Bad
/*
for (const x in [3, 4, 5]) {
	console.log(x);
}
*/
// Good
// still not okay because not allowed by this rules: no-restricted-syntax, guard-for-in
for (const x in { a: 3, b: 4, c: 5 }) {
	console.log(x);
}

Disallows explicit type declarations for variables or parameters initialized to a number, string, or boolean.

✅ Enabled (error)

// Bad
/*
(async () => {
	const foo: number = 5;
	const bar: boolean = true;
	const baz: string = 'str';
})();
*/
// Good
(async () => {
	const foo = 5;
	const bar = true;
	const baz = 'str';
})();

Enforce valid definition of new and constructor. (no-misused-new)

✅ Enabled (error)

// Bad
/*
(async () => {
	class C {
		new(): C;
	}

	interface IFoo {
		new (): IFoo;
		constructor(): void;
	}
})();
*/
// Good
(async () => {
	class C {
		public constructor() {}
	}
	interface IFoo {
		new (): C;
	}
})();

Disallow the use of custom TypeScript modules and namespaces (no-namespace)

✅ Enabled (error)

// Bad
/*
module foo {}
namespace foo {}
declare module foo {}
declare namespace foo {}
*/
// Good
declare module 'foo' {}

Disallows non-null assertions using the ! postfix operator (no-non-null-assertion)

✅ Enabled (error)

// Bad
/*
(() => {
	interface IFoo {
		bar?: string;
	}

	const foo: IFoo = { bar: 'bar' };
	const includesBaz: boolean = foo.bar!.includes('baz');
})();
*/
// Good
(() => {
	interface IFoo {
		bar?: string;
	}

	const foo: IFoo = { bar: 'baz' };
	const includesBaz: boolean = (foo.bar || '').includes('baz');
})();

Disallow the use of parameter properties in class constructors. (no-parameter-properties)

✅ Enabled (error)

// Bad
/*
(() => {
	class Foo {
		constructor(readonly name: string) {}
	}
	class Foo {
		constructor(private name: string) {}
	}
	class Foo {
		constructor(protected name: string) {}
	}
	class Foo {
		constructor(public name: string) {}
	}
})();
*/
// Good
(() => {
	class Foo {
		constructor(name: string) {}
	}
})();

Disallows invocation of require() (no-require-imports)

✅ Enabled (error)

// Bad
/*
const eslint = require('eslint');
*/
// Good
import eslint from 'eslint';

Disallow aliasing this (no-this-alias)

❌ Disabled

// Bad
/*
(() => {
	const self = this;

	setTimeout(() => {
		self.doWork();
	});
})();
*/
// Good
(() => {
	// already covered by consistent-this
	const _this = this;

	setTimeout(() => {
		_this.doWork();
	});
})();

Disallow the use of type aliases (no-type-alias)

❌ Disabled

// Good
(() => {
	// primitives
	type Foo = 'a' | 'b';

	type Foo2 = string;

	type Foo3 = string[];

	// reference types
	interface IBar {}
	class Baz implements IBar {}

	type Foo5 = IBar & Baz;
})();

Warns when a namespace qualifier is unnecessary. (no-unnecessary-qualifier)

✅ Enabled (error)

// Bad
/*
namespace A {
	export type B = number;
	const x: A.B = 3;
}
*/
// Good
namespace X {
	export type B = number;
}
namespace Y {
	export const x: X.B = 3;
}

Warns if a type assertion does not change the type of an expression (no-unnecessary-type-assertion)

✅ Enabled (error)

// Bad
/*
(() => {
	function foo(x: number): number {
		return x!; // unnecessary non-null
	}
})();
*/
// Good
(() => {
	function foo(x: number | undefined): number {
		return x!;
	}
})();

Disallow unused variables (no-unused-vars)

✅ Enabled (error)

// Bad
/*
// Write-only variables are not considered as used.
let y = 10;
y = 5;

// A read for a modification of itself is not considered as used.
let z = 0;
z = z + 1;
*/
// Good
// Write-only variables are not considered as used.
let y = 10;
y = 5;

// A read for a modification of itself is not considered as used.
let z = 0;
z = z + y;

console.log(z);

Disallow the use of variables before they are defined (no-use-before-define)

✅ Enabled (error)

// Bad
/*
(() => {
	alert(a);
	const a = 10;
})();
*/
// Good
(() => {
	const a = 10;
	alert(a);
})();

Disallow the use of variables before they are defined (no-use-before-define)

✅ Enabled (error)

// Bad
/*
(() => {
	class A {
		constructor() {}
	}
})();
*/
// Good
(() => {
	class A {
		public constructor() {
			this._doSomething();
		}
		private _doSomething() {
			document.write('something');
		}
	}
})();

Disallows the use of require statements except in import statements (no-var-requires)

✅ Enabled (error)

// Bad
/*
(() => {
	var foo1 = require('foo');
	const foo2 = require('foo');
	let foo3 = require('foo');
})();
*/
// Good
import eslint from 'eslint';

Use function types instead of interfaces with call signatures (prefer-function-type)

✅ Enabled (error)

// Bad
/*
(() => {
	interface IFoo {
		(): string;
	}

	function foo(bar: { (): number }): number {
		return bar();
	}

	interface IFoo2 extends Function {
		(): void;
	}
})();
*/
// Good
(() => {
	interface IFoo {
		bar: number;
		(): void;
	}

	function foo(bar: { baz: number;(): string }): string {
		return bar();
	}

	interface IFoo2 {
		bar: string;
	}
	interface IBar extends IFoo2 {
		(): void;
	}
})();

Prefer an interface declaration over a type literal (type T = { ... }) (prefer-interface)

✅ Enabled (error)

// Bad
/*
(() => {
	type Test = { x: number };
})();
*/
// Good
(() => {
	interface ITest {
		x: number;
	}
})();

Functions that return promises must be async (promise-function-async)

✅ Enabled (error)

// Bad
/*
(() => {
	const arrowFunctionReturnsPromise = () => Promise.resolve('value');

	function functionReturnsPromise() {
		return Math.random() > 0.5 ? Promise.resolve('value') : false;
	}
})();
*/
// Good
(() => {
	const arrowFunctionReturnsPromise = async () => 'value';

	async function functionReturnsPromise() {
		return Math.random() > 0.5 ? 'value' : false;
	}
})();

When adding two variables, operands must both be of type number or of type string.

✅ Enabled (error)

// Bad
/*
(() => {
	const foo = '5.5' + 5;
})();
*/
// Good
(() => {
	const foo = parseInt('5.5', 10) + 10;
})();

Disallow /// comments (triple-slash-reference)

✅ Enabled (error)

// Good
(() => {
	/// <reference path="../../../../node_modules/@types/react/index.d.ts" />
})();

Require consistent spacing around type annotations

✅ Enabled (error)

// Bad
/*
(() => {
	const foo:string = 'bar';
})();
*/
// Good
(() => {
	const foo: string = 'bar';
})();

Warns for any two overloads that could be unified into one by using a union or an optional/rest parameter.

✅ Enabled (error)

// Bad
/*
(() => {
	interface IFoo {
		foo(sn: string | number): void;
		foo(s: string): void;
		foo(n: number): void;
		bar(): void;
	}
})();
*/
// Good
(() => {
	interface IFoo {
		foo(sn: string | number): void;
		bar(): void;
	}
})();