diff --git a/packages/backend/.eslintrc.js b/packages/backend/.eslintrc.js
index 952a2ee9ef..bafd0c9b63 100644
--- a/packages/backend/.eslintrc.js
+++ b/packages/backend/.eslintrc.js
@@ -22,6 +22,7 @@ module.exports = {
 		'eol-last': ['error', 'always'],
 		'semi': ['error', 'always'],
 		'quotes': ['warn', 'single'],
+		'comma-dangle': ['warn', 'always-multiline'],
 		'keyword-spacing': ['error', {
 			'before': true,
 			'after': true,
@@ -44,6 +45,8 @@ module.exports = {
 		'no-multi-spaces': ['warn'],
 		'no-control-regex': ['warn'],
 		'no-empty': ['warn'],
+		'no-inner-declarations': ['off'],
+		'no-sparse-arrays': ['off'],
 		'@typescript-eslint/no-var-requires': ['warn'],
 		'@typescript-eslint/no-inferrable-types': ['warn'],
 		'@typescript-eslint/no-empty-function': ['off'],
diff --git a/packages/backend/@types/jsrsasign.d.ts b/packages/backend/@types/jsrsasign.d.ts
index bc9d746f7e..bb52f8f64e 100644
--- a/packages/backend/@types/jsrsasign.d.ts
+++ b/packages/backend/@types/jsrsasign.d.ts
@@ -171,7 +171,7 @@ declare module 'jsrsasign' {
 
 		public static getTLVbyList(h: ASN1S, currentIndex: Idx<ASN1ObjectString>, nthList: Mutable<Nth[]>, checkingTag?: string): ASN1TLV;
 
-		// tslint:disable-next-line:bool-param-default
+		// eslint:disable-next-line:bool-param-default
 		public static getVbyList(h: ASN1S, currentIndex: Idx<ASN1ObjectString>, nthList: Mutable<Nth[]>, checkingTag?: string, removeUnusedbits?: boolean): ASN1V;
 
 		public static hextooidstr(hex: ASN1OIDV): OID;
diff --git a/packages/backend/src/mfm/from-html.ts b/packages/backend/src/mfm/from-html.ts
index de6aa3d0cc..43e16d80c5 100644
--- a/packages/backend/src/mfm/from-html.ts
+++ b/packages/backend/src/mfm/from-html.ts
@@ -48,9 +48,10 @@ export function fromHtml(html: string, hashtagNames?: string[]): string | null {
 		if (!treeAdapter.isElementNode(node)) return;
 
 		switch (node.nodeName) {
-			case 'br':
+			case 'br': {
 				text += '\n';
 				break;
+			}
 
 			case 'a':
 			{
diff --git a/packages/backend/src/misc/cafy-id.ts b/packages/backend/src/misc/cafy-id.ts
index 39886611e1..dd81c5c4cf 100644
--- a/packages/backend/src/misc/cafy-id.ts
+++ b/packages/backend/src/misc/cafy-id.ts
@@ -1,5 +1,6 @@
 import { Context } from 'cafy';
 
+// eslint-disable-next-line @typescript-eslint/ban-types
 export class ID<Maybe = string> extends Context<string | (Maybe extends {} ? string : Maybe)> {
 	public readonly name = 'ID';
 
diff --git a/packages/backend/src/misc/gen-avatar.ts b/packages/backend/src/misc/gen-avatar.ts
index f03ca9f96d..8838ec8d15 100644
--- a/packages/backend/src/misc/gen-avatar.ts
+++ b/packages/backend/src/misc/gen-avatar.ts
@@ -56,7 +56,7 @@ export function genAvatar(seed: string, stream: WriteStream): Promise<void> {
 	// 1*n (filled by false)
 	const center: boolean[] = new Array(n).fill(false);
 
-	// tslint:disable-next-line:prefer-for-of
+	// eslint:disable-next-line:prefer-for-of
 	for (let x = 0; x < side.length; x++) {
 		for (let y = 0; y < side[x].length; y++) {
 			side[x][y] = rand(3) === 0;
diff --git a/packages/backend/src/prelude/array.ts b/packages/backend/src/prelude/array.ts
index d63f0475d0..1e9e62b895 100644
--- a/packages/backend/src/prelude/array.ts
+++ b/packages/backend/src/prelude/array.ts
@@ -87,7 +87,7 @@ export function groupOn<T, S>(f: (x: T) => S, xs: T[]): T[][] {
 export function groupByX<T>(collections: T[], keySelector: (x: T) => string) {
 	return collections.reduce((obj: Record<string, T[]>, item: T) => {
 		const key = keySelector(item);
-		if (!obj.hasOwnProperty(key)) {
+		if (!Object.prototype.hasOwnProperty.call(obj, key)) {
 			obj[key] = [];
 		}
 
diff --git a/packages/backend/src/prelude/url.ts b/packages/backend/src/prelude/url.ts
index c7f2b7c1e7..a4f2f7f5a8 100644
--- a/packages/backend/src/prelude/url.ts
+++ b/packages/backend/src/prelude/url.ts
@@ -1,4 +1,4 @@
-export function query(obj: {}): string {
+export function query(obj: Record<string, unknown>): string {
 	const params = Object.entries(obj)
 		.filter(([, v]) => Array.isArray(v) ? v.length : v !== undefined)
 		.reduce((a, [k, v]) => (a[k] = v, a), {} as Record<string, any>);
diff --git a/packages/backend/src/queue/processors/object-storage/clean-remote-files.ts b/packages/backend/src/queue/processors/object-storage/clean-remote-files.ts
index 3b2e4ea939..a094c39d5d 100644
--- a/packages/backend/src/queue/processors/object-storage/clean-remote-files.ts
+++ b/packages/backend/src/queue/processors/object-storage/clean-remote-files.ts
@@ -7,7 +7,7 @@ import { MoreThan, Not, IsNull } from 'typeorm';
 
 const logger = queueLogger.createSubLogger('clean-remote-files');
 
-export default async function cleanRemoteFiles(job: Bull.Job<{}>, done: any): Promise<void> {
+export default async function cleanRemoteFiles(job: Bull.Job<Record<string, unknown>>, done: any): Promise<void> {
 	logger.info(`Deleting cached remote files...`);
 
 	let deletedCount = 0;
diff --git a/packages/backend/src/queue/processors/system/index.ts b/packages/backend/src/queue/processors/system/index.ts
index 52b7868105..8460ea0a9b 100644
--- a/packages/backend/src/queue/processors/system/index.ts
+++ b/packages/backend/src/queue/processors/system/index.ts
@@ -3,9 +3,9 @@ import { resyncCharts } from './resync-charts';
 
 const jobs = {
 	resyncCharts,
-} as Record<string, Bull.ProcessCallbackFunction<{}> | Bull.ProcessPromiseFunction<{}>>;
+} as Record<string, Bull.ProcessCallbackFunction<Record<string, unknown>> | Bull.ProcessPromiseFunction<Record<string, unknown>>>;
 
-export default function(dbQueue: Bull.Queue<{}>) {
+export default function(dbQueue: Bull.Queue<Record<string, unknown>>) {
 	for (const [k, v] of Object.entries(jobs)) {
 		dbQueue.process(k, v);
 	}
diff --git a/packages/backend/src/queue/processors/system/resync-charts.ts b/packages/backend/src/queue/processors/system/resync-charts.ts
index b36b024cfb..78a70bb981 100644
--- a/packages/backend/src/queue/processors/system/resync-charts.ts
+++ b/packages/backend/src/queue/processors/system/resync-charts.ts
@@ -5,7 +5,7 @@ import { driveChart, notesChart, usersChart } from '@/services/chart/index';
 
 const logger = queueLogger.createSubLogger('resync-charts');
 
-export default async function resyncCharts(job: Bull.Job<{}>, done: any): Promise<void> {
+export async function resyncCharts(job: Bull.Job<Record<string, unknown>>, done: any): Promise<void> {
 	logger.info(`Resync charts...`);
 
 	// TODO: ユーザーごとのチャートも更新する
diff --git a/packages/backend/src/queue/queues.ts b/packages/backend/src/queue/queues.ts
index a66a7ca451..b1d790fcb1 100644
--- a/packages/backend/src/queue/queues.ts
+++ b/packages/backend/src/queue/queues.ts
@@ -2,7 +2,7 @@ import config from '@/config/index';
 import { initialize as initializeQueue } from './initialize';
 import { DeliverJobData, InboxJobData, DbJobData, ObjectStorageJobData } from './types';
 
-export const systemQueue = initializeQueue<{}>('system');
+export const systemQueue = initializeQueue<Record<string, unknown>>('system');
 export const deliverQueue = initializeQueue<DeliverJobData>('deliver', config.deliverJobPerSec || 128);
 export const inboxQueue = initializeQueue<InboxJobData>('inbox', config.inboxJobPerSec || 16);
 export const dbQueue = initializeQueue<DbJobData>('db');
diff --git a/packages/backend/src/queue/types.ts b/packages/backend/src/queue/types.ts
index 39cab29966..c8c7147152 100644
--- a/packages/backend/src/queue/types.ts
+++ b/packages/backend/src/queue/types.ts
@@ -33,7 +33,7 @@ export type DbUserImportJobData = {
 	fileId: DriveFile['id'];
 };
 
-export type ObjectStorageJobData = ObjectStorageFileJobData | {};
+export type ObjectStorageJobData = ObjectStorageFileJobData | Record<string, unknown>;
 
 export type ObjectStorageFileJobData = {
 	key: string;
diff --git a/packages/backend/src/remote/activitypub/models/person.ts b/packages/backend/src/remote/activitypub/models/person.ts
index eb8c00a10b..95db46bff2 100644
--- a/packages/backend/src/remote/activitypub/models/person.ts
+++ b/packages/backend/src/remote/activitypub/models/person.ts
@@ -274,7 +274,7 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<Us
  * @param resolver Resolver
  * @param hint Hint of Person object (この値が正当なPersonの場合、Remote resolveをせずに更新に利用します)
  */
-export async function updatePerson(uri: string, resolver?: Resolver | null, hint?: object): Promise<void> {
+export async function updatePerson(uri: string, resolver?: Resolver | null, hint?: Record<string, unknown>): Promise<void> {
 	if (typeof uri !== 'string') throw new Error('uri is not string');
 
 	// URIがこのサーバーを指しているならスキップ
diff --git a/packages/backend/src/remote/activitypub/renderer/ordered-collection.ts b/packages/backend/src/remote/activitypub/renderer/ordered-collection.ts
index 68870a0ecd..c4b4337af8 100644
--- a/packages/backend/src/remote/activitypub/renderer/ordered-collection.ts
+++ b/packages/backend/src/remote/activitypub/renderer/ordered-collection.ts
@@ -6,7 +6,7 @@
  * @param last URL of last page (optional)
  * @param orderedItems attached objects (optional)
  */
-export default function(id: string | null, totalItems: any, first?: string, last?: string, orderedItems?: object) {
+export default function(id: string | null, totalItems: any, first?: string, last?: string, orderedItems?: Record<string, unknown>) {
 	const page: any = {
 		id,
 		type: 'OrderedCollection',
diff --git a/packages/backend/src/server/api/define.ts b/packages/backend/src/server/api/define.ts
index 4bd8f95e31..48253e78e0 100644
--- a/packages/backend/src/server/api/define.ts
+++ b/packages/backend/src/server/api/define.ts
@@ -20,7 +20,7 @@ type SimpleUserInfo = {
 };
 
 type Params<T extends IEndpointMeta> = {
-	[P in keyof T['params']]: NonNullable<T['params']>[P]['transform'] extends Function
+	[P in keyof T['params']]: NonNullable<T['params']>[P]['transform'] extends () => any
 		? ReturnType<NonNullable<T['params']>[P]['transform']>
 		: NonNullable<T['params']>[P]['default'] extends null | number | string
 			? NonOptional<ReturnType<NonNullable<T['params']>[P]['validator']['get']>[0]>
@@ -30,7 +30,7 @@ type Params<T extends IEndpointMeta> = {
 export type Response = Record<string, any> | void;
 
 type executor<T extends IEndpointMeta> =
-	(params: Params<T>, user: T['requireCredential'] extends true ? SimpleUserInfo : SimpleUserInfo | null, token: AccessToken | null, file?: any, cleanup?: Function) =>
+	(params: Params<T>, user: T['requireCredential'] extends true ? SimpleUserInfo : SimpleUserInfo | null, token: AccessToken | null, file?: any, cleanup?: () => any) =>
 		Promise<T['res'] extends undefined ? Response : SchemaType<NonNullable<T['res']>>>;
 
 export default function <T extends IEndpointMeta>(meta: T, cb: executor<T>)
@@ -74,7 +74,7 @@ function getParams<T extends IEndpointMeta>(defs: T, params: any): [Params<T>, A
 			});
 			return true;
 		} else {
-			if (v === undefined && def.hasOwnProperty('default')) {
+			if (v === undefined && Object.prototype.hasOwnProperty.call(def, 'default')) {
 				x[k] = def.default;
 			} else {
 				x[k] = v;
diff --git a/packages/backend/src/server/api/endpoints/channels/update.ts b/packages/backend/src/server/api/endpoints/channels/update.ts
index 9b447bd04b..05f279d6ac 100644
--- a/packages/backend/src/server/api/endpoints/channels/update.ts
+++ b/packages/backend/src/server/api/endpoints/channels/update.ts
@@ -69,7 +69,7 @@ export default define(meta, async (ps, me) => {
 		throw new ApiError(meta.errors.accessDenied);
 	}
 
-	// tslint:disable-next-line:no-unnecessary-initializer
+	// eslint:disable-next-line:no-unnecessary-initializer
 	let banner = undefined;
 	if (ps.bannerId != null) {
 		banner = await DriveFiles.findOne({
diff --git a/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts b/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts
index b4d3af235a..e06d0a9f68 100644
--- a/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts
+++ b/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts
@@ -75,7 +75,7 @@ export default define(meta, async (ps, user) => {
 
 	const flags = attestation.authData[32];
 
-	// tslint:disable-next-line:no-bitwise
+	// eslint:disable-next-line:no-bitwise
 	if (!(flags & 1)) {
 		throw new Error('user not present');
 	}
diff --git a/packages/backend/src/server/api/limiter.ts b/packages/backend/src/server/api/limiter.ts
index 1e2fe5bcb3..82a8613c90 100644
--- a/packages/backend/src/server/api/limiter.ts
+++ b/packages/backend/src/server/api/limiter.ts
@@ -10,16 +10,16 @@ const logger = new Logger('limiter');
 export default (endpoint: IEndpoint, user: User) => new Promise<void>((ok, reject) => {
 	const limitation = endpoint.meta.limit!;
 
-	const key = limitation.hasOwnProperty('key')
+	const key = Object.prototype.hasOwnProperty.call(limitation, 'key')
 		? limitation.key
 		: endpoint.name;
 
 	const hasShortTermLimit =
-		limitation.hasOwnProperty('minInterval');
+		Object.prototype.hasOwnProperty.call(limitation, 'minInterval');
 
 	const hasLongTermLimit =
-		limitation.hasOwnProperty('duration') &&
-		limitation.hasOwnProperty('max');
+		Object.prototype.hasOwnProperty.call(limitation, 'duration') &&
+		Object.prototype.hasOwnProperty.call(limitation, 'max');
 
 	if (hasShortTermLimit) {
 		min();
diff --git a/packages/backend/src/server/api/stream/channels/games/reversi.ts b/packages/backend/src/server/api/stream/channels/games/reversi.ts
index 3b89aac35c..399750c26a 100644
--- a/packages/backend/src/server/api/stream/channels/games/reversi.ts
+++ b/packages/backend/src/server/api/stream/channels/games/reversi.ts
@@ -19,7 +19,7 @@ export default class extends Channel {
 	@autobind
 	public async onMessage(type: string, body: any) {
 		switch (type) {
-			case 'ping':
+			case 'ping': {
 				if (body.id == null) return;
 				const matching = await ReversiMatchings.findOne({
 					parentId: this.user!.id,
@@ -28,6 +28,7 @@ export default class extends Channel {
 				if (matching == null) return;
 				publishMainStream(matching.childId, 'reversiInvited', await ReversiMatchings.pack(matching, { id: matching.childId }));
 				break;
+			}
 		}
 	}
 }
diff --git a/packages/backend/src/server/api/stream/types.ts b/packages/backend/src/server/api/stream/types.ts
index 70eb5c5ce5..f4302f64a0 100644
--- a/packages/backend/src/server/api/stream/types.ts
+++ b/packages/backend/src/server/api/stream/types.ts
@@ -31,7 +31,7 @@ export interface BroadcastTypes {
 }
 
 export interface UserStreamTypes {
-	terminate: {};
+	terminate: Record<string, unknown>;
 	followChannel: Channel;
 	unfollowChannel: Channel;
 	updateUserProfile: UserProfile;
diff --git a/packages/backend/src/services/chart/core.ts b/packages/backend/src/services/chart/core.ts
index c0d3280c2b..78b7dd1359 100644
--- a/packages/backend/src/services/chart/core.ts
+++ b/packages/backend/src/services/chart/core.ts
@@ -70,7 +70,7 @@ export default abstract class Chart<T extends Record<string, any>> {
 
 	@autobind
 	private static convertSchemaToFlatColumnDefinitions(schema: SimpleSchema) {
-		const columns = {} as any;
+		const columns = {} as Record<string, unknown>;
 		const flatColumns = (x: Obj, path?: string) => {
 			for (const [k, v] of Object.entries(x)) {
 				const p = path ? `${path}${this.columnDot}${k}` : k;
@@ -93,8 +93,8 @@ export default abstract class Chart<T extends Record<string, any>> {
 	}
 
 	@autobind
-	private static convertFlattenColumnsToObject(x: Record<string, any>): Record<string, any> {
-		const obj = {} as any;
+	private static convertFlattenColumnsToObject(x: Record<string, unknown>): Record<string, unknown> {
+		const obj = {} as Record<string, unknown>;
 		for (const k of Object.keys(x).filter(k => k.startsWith(Chart.columnPrefix))) {
 			// now k is ___x_y_z
 			const path = k.substr(Chart.columnPrefix.length).split(Chart.columnDot).join('.');
@@ -104,7 +104,7 @@ export default abstract class Chart<T extends Record<string, any>> {
 	}
 
 	@autobind
-	private static convertObjectToFlattenColumns(x: Record<string, any>) {
+	private static convertObjectToFlattenColumns(x: Record<string, unknown>) {
 		const columns = {} as Record<string, number | unknown[]>;
 		const flatten = (x: Obj, path?: string) => {
 			for (const [k, v] of Object.entries(x)) {
@@ -121,9 +121,9 @@ export default abstract class Chart<T extends Record<string, any>> {
 	}
 
 	@autobind
-	private static countUniqueFields(x: Record<string, any>) {
+	private static countUniqueFields(x: Record<string, unknown>) {
 		const exec = (x: Obj) => {
-			const res = {} as Record<string, any>;
+			const res = {} as Record<string, unknown>;
 			for (const [k, v] of Object.entries(x)) {
 				if (typeof v === 'object' && !Array.isArray(v)) {
 					res[k] = exec(v);
@@ -140,7 +140,7 @@ export default abstract class Chart<T extends Record<string, any>> {
 
 	@autobind
 	private static convertQuery(diff: Record<string, number | unknown[]>) {
-		const query: Record<string, Function> = {};
+		const query: Record<string, () => string> = {};
 
 		for (const [k, v] of Object.entries(diff)) {
 			if (typeof v === 'number') {
@@ -337,7 +337,7 @@ export default abstract class Chart<T extends Record<string, any>> {
 	}
 
 	@autobind
-	public async save() {
+	public async save(): Promise<void> {
 		if (this.buffer.length === 0) {
 			logger.info(`${this.name}: Write skipped`);
 			return;
diff --git a/packages/backend/src/services/stream.ts b/packages/backend/src/services/stream.ts
index 2c308a1b54..0901857c33 100644
--- a/packages/backend/src/services/stream.ts
+++ b/packages/backend/src/services/stream.ts
@@ -37,74 +37,74 @@ class Publisher {
 			channel: channel,
 			message: message
 		}));
-	}
+	};
 
 	public publishInternalEvent = <K extends keyof InternalStreamTypes>(type: K, value?: InternalStreamTypes[K]): void => {
 		this.publish('internal', type, typeof value === 'undefined' ? null : value);
-	}
+	};
 
 	public publishUserEvent = <K extends keyof UserStreamTypes>(userId: User['id'], type: K, value?: UserStreamTypes[K]): void => {
 		this.publish(`user:${userId}`, type, typeof value === 'undefined' ? null : value);
-	}
+	};
 
 	public publishBroadcastStream = <K extends keyof BroadcastTypes>(type: K, value?: BroadcastTypes[K]): void => {
 		this.publish('broadcast', type, typeof value === 'undefined' ? null : value);
-	}
+	};
 
 	public publishMainStream = <K extends keyof MainStreamTypes>(userId: User['id'], type: K, value?: MainStreamTypes[K]): void => {
 		this.publish(`mainStream:${userId}`, type, typeof value === 'undefined' ? null : value);
-	}
+	};
 
 	public publishDriveStream = <K extends keyof DriveStreamTypes>(userId: User['id'], type: K, value?: DriveStreamTypes[K]): void => {
 		this.publish(`driveStream:${userId}`, type, typeof value === 'undefined' ? null : value);
-	}
+	};
 
 	public publishNoteStream = <K extends keyof NoteStreamTypes>(noteId: Note['id'], type: K, value?: NoteStreamTypes[K]): void => {
 		this.publish(`noteStream:${noteId}`, type, {
 			id: noteId,
 			body: value
 		});
-	}
+	};
 
 	public publishChannelStream = <K extends keyof ChannelStreamTypes>(channelId: Channel['id'], type: K, value?: ChannelStreamTypes[K]): void => {
 		this.publish(`channelStream:${channelId}`, type, typeof value === 'undefined' ? null : value);
-	}
+	};
 
 	public publishUserListStream = <K extends keyof UserListStreamTypes>(listId: UserList['id'], type: K, value?: UserListStreamTypes[K]): void => {
 		this.publish(`userListStream:${listId}`, type, typeof value === 'undefined' ? null : value);
-	}
+	};
 
 	public publishAntennaStream = <K extends keyof AntennaStreamTypes>(antennaId: Antenna['id'], type: K, value?: AntennaStreamTypes[K]): void => {
 		this.publish(`antennaStream:${antennaId}`, type, typeof value === 'undefined' ? null : value);
-	}
+	};
 
 	public publishMessagingStream = <K extends keyof MessagingStreamTypes>(userId: User['id'], otherpartyId: User['id'], type: K, value?: MessagingStreamTypes[K]): void => {
 		this.publish(`messagingStream:${userId}-${otherpartyId}`, type, typeof value === 'undefined' ? null : value);
-	}
+	};
 
 	public publishGroupMessagingStream = <K extends keyof GroupMessagingStreamTypes>(groupId: UserGroup['id'], type: K, value?: GroupMessagingStreamTypes[K]): void => {
 		this.publish(`messagingStream:${groupId}`, type, typeof value === 'undefined' ? null : value);
-	}
+	};
 
 	public publishMessagingIndexStream = <K extends keyof MessagingIndexStreamTypes>(userId: User['id'], type: K, value?: MessagingIndexStreamTypes[K]): void => {
 		this.publish(`messagingIndexStream:${userId}`, type, typeof value === 'undefined' ? null : value);
-	}
+	};
 
 	public publishReversiStream = <K extends keyof ReversiStreamTypes>(userId: User['id'], type: K, value?: ReversiStreamTypes[K]): void => {
 		this.publish(`reversiStream:${userId}`, type, typeof value === 'undefined' ? null : value);
-	}
+	};
 
 	public publishReversiGameStream = <K extends keyof ReversiGameStreamTypes>(gameId: ReversiGame['id'], type: K, value?: ReversiGameStreamTypes[K]): void => {
 		this.publish(`reversiGameStream:${gameId}`, type, typeof value === 'undefined' ? null : value);
-	}
+	};
 
 	public publishNotesStream = (note: Packed<'Note'>): void => {
 		this.publish('notesStream', null, note);
-	}
+	};
 
 	public publishAdminStream = <K extends keyof AdminStreamTypes>(userId: User['id'], type: K, value?: AdminStreamTypes[K]): void => {
 		this.publish(`adminStream:${userId}`, type, typeof value === 'undefined' ? null : value);
-	}
+	};
 }
 
 const publisher = new Publisher();