diff --git a/packages/backend/src/services/chart/core.ts b/packages/backend/src/services/chart/core.ts
index 61a7575706..04e98f97e8 100644
--- a/packages/backend/src/services/chart/core.ts
+++ b/packages/backend/src/services/chart/core.ts
@@ -17,8 +17,27 @@ const columnPrefix = '___' as const;
 const uniqueTempColumnPrefix = 'unique_temp___' as const;
 const columnDot = '_' as const;
 
+type Schema = Record<string, {
+	uniqueIncrement?: boolean;
+
+	intersection?: string[] | ReadonlyArray<string>;
+
+	range?: 'big' | 'small' | 'medium';
+
+	// previousな値を引き継ぐかどうか
+	accumulate?: boolean;
+}>;
+
 type KeyToColumnName<T extends string> = T extends `${infer R1}.${infer R2}` ? `${R1}${typeof columnDot}${KeyToColumnName<R2>}` : T;
 
+type Columns<S extends Schema> = {
+	[K in keyof S as `${typeof columnPrefix}${KeyToColumnName<string & K>}`]: number;
+};
+
+type TempColumnsForUnique<S extends Schema> = {
+	[K in keyof S as `${typeof uniqueTempColumnPrefix}${KeyToColumnName<string & K>}`]: S[K]['uniqueIncrement'] extends true ? string[] : never;
+};
+
 type RawRecord<S extends Schema> = {
 	id: number;
 
@@ -31,11 +50,7 @@ type RawRecord<S extends Schema> = {
 	 * 集計日時のUnixタイムスタンプ(秒)
 	 */
 	date: number;
-} & {
-	[K in keyof S as `${typeof uniqueTempColumnPrefix}${KeyToColumnName<string & K>}`]: S[K]['uniqueIncrement'] extends true ? string[] : never;
-} & {
-	[K in keyof S as `${typeof columnPrefix}${KeyToColumnName<string & K>}`]: number;
-};
+} & TempColumnsForUnique<S> & Columns<S>;
 
 const camelToSnake = (str: string): string => {
 	return str.replace(/([A-Z])/g, s => '_' + s.charAt(0).toLowerCase());
@@ -43,17 +58,6 @@ const camelToSnake = (str: string): string => {
 
 const removeDuplicates = (array: any[]) => Array.from(new Set(array));
 
-type Schema = Record<string, {
-	uniqueIncrement?: boolean;
-
-	intersection?: string[] | ReadonlyArray<string>;
-
-	range?: 'big' | 'small' | 'medium';
-
-	// previousな値を引き継ぐかどうか
-	accumulate?: boolean;
-}>;
-
 type Commit<S extends Schema> = {
 	[K in keyof S]?: S[K]['uniqueIncrement'] extends true ? string[] : number;
 };
@@ -78,8 +82,11 @@ export default abstract class Chart<T extends Schema> {
 		diff: Commit<T>;
 		group: string | null;
 	}[] = [];
-	protected repositoryForHour: Repository<RawRecord<T>>;
-	protected repositoryForDay: Repository<RawRecord<T>>;
+	// ↓にしたいけどfindOneとかで型エラーになる
+	//private repositoryForHour: Repository<RawRecord<T>>;
+	//private repositoryForDay: Repository<RawRecord<T>>;
+	private repositoryForHour: Repository<{ id: number; group?: string | null; date: number; }>;
+	private repositoryForDay: Repository<{ id: number; group?: string | null; date: number; }>;
 
 	/**
 	 * 1日に一回程度実行されれば良いような計算処理を入れる(主にCASCADE削除などアプリケーション側で感知できない変動によるズレの修正用)
@@ -196,23 +203,23 @@ export default abstract class Chart<T extends Schema> {
 		this.schema = schema;
 
 		const { hour, day } = Chart.schemaToEntity(name, schema, grouped);
-		this.repositoryForHour = getRepository<RawRecord<T>>(hour);
-		this.repositoryForDay = getRepository<RawRecord<T>>(day);
+		this.repositoryForHour = getRepository<{ id: number; group?: string | null; date: number; }>(hour);
+		this.repositoryForDay = getRepository<{ id: number; group?: string | null; date: number; }>(day);
 	}
 
 	@autobind
 	private convertRawRecord(x: RawRecord<T>): KVs<T> {
-		const kvs = {} as KVs<T>;
-		for (const k of Object.keys(x).filter(k => k.startsWith(columnPrefix))) {
-			kvs[k.substr(columnPrefix.length).split(columnDot).join('.')] = x[k];
+		const kvs = {} as Record<string, number>;
+		for (const k of Object.keys(x).filter((k) => k.startsWith(columnPrefix)) as (keyof Columns<T>)[]) {
+			kvs[(k as string).substr(columnPrefix.length).split(columnDot).join('.')] = x[k];
 		}
-		return kvs;
+		return kvs as KVs<T>;
 	}
 
 	@autobind
 	private getNewLog(latest: KVs<T> | null): KVs<T> {
 		const log = {} as Record<keyof T, number>;
-		for (const [k, v] of Object.entries(this.schema)) {
+		for (const [k, v] of Object.entries(this.schema) as ([keyof typeof this['schema'], this['schema'][string]])[]) {
 			if (v.accumulate && latest) {
 				log[k] = latest[k];
 			} else {
@@ -235,7 +242,7 @@ export default abstract class Chart<T extends Schema> {
 			order: {
 				date: -1,
 			},
-		}).then(x => x || null);
+		}).then(x => x ?? null) as Promise<RawRecord<T> | null>;
 	}
 
 	/**
@@ -259,7 +266,7 @@ export default abstract class Chart<T extends Schema> {
 		const currentLog = await repository.findOne({
 			date: Chart.dateToTimestamp(current),
 			...(group ? { group: group } : {}),
-		});
+		}) as RawRecord<T>;
 
 		// ログがあればそれを返して終了
 		if (currentLog != null) {
@@ -299,7 +306,7 @@ export default abstract class Chart<T extends Schema> {
 			const currentLog = await repository.findOne({
 				date: date,
 				...(group ? { group: group } : {}),
-			});
+			}) as RawRecord<T>;
 
 			// ログがあればそれを返して終了
 			if (currentLog != null) return currentLog;
@@ -315,7 +322,7 @@ export default abstract class Chart<T extends Schema> {
 				date: date,
 				...(group ? { group: group } : {}),
 				...columns,
-			}).then(x => repository.findOneOrFail(x.identifiers[0]));
+			}).then(x => repository.findOneOrFail(x.identifiers[0])) as RawRecord<T>;
 
 			logger.info(`${this.name + (group ? `:${group}` : '')}(${span}): New commit created`);
 
@@ -349,7 +356,7 @@ export default abstract class Chart<T extends Schema> {
 		// これを回避するための実装は複雑になりそうなため、一旦保留。
 
 		const update = async (logHour: RawRecord<T>, logDay: RawRecord<T>): Promise<void> => {
-			const finalDiffs = {} as Record<string, number | unknown[]>;
+			const finalDiffs = {} as Record<string, number | string[]>;
 
 			for (const diff of this.buffer.filter(q => q.group == null || (q.group === logHour.group)).map(q => q.diff)) {
 				for (const [k, v] of Object.entries(diff)) {
@@ -359,23 +366,23 @@ export default abstract class Chart<T extends Schema> {
 						if (typeof finalDiffs[k] === 'number') {
 							(finalDiffs[k] as number) += v as number;
 						} else {
-							(finalDiffs[k] as unknown[]) = (finalDiffs[k] as unknown[]).concat(v);
+							(finalDiffs[k] as string[]) = (finalDiffs[k] as string[]).concat(v);
 						}
 					}
 				}
 			}
 
-			const queryForHour: Record<string, number | (() => string)> = {};
-			const queryForDay: Record<string, number | (() => string)> = {};
+			const queryForHour: Record<keyof RawRecord<T>, number | (() => string)> = {} as any;
+			const queryForDay: Record<keyof RawRecord<T>, number | (() => string)> = {} as any;
 			for (const [k, v] of Object.entries(finalDiffs)) {
 				if (typeof v === 'number') {
-					const name = columnPrefix + k.replaceAll('.', columnDot);
+					const name = columnPrefix + k.replaceAll('.', columnDot) as keyof Columns<T>;
 					if (v > 0) queryForHour[name] = () => `"${name}" + ${v}`;
 					if (v < 0) queryForHour[name] = () => `"${name}" - ${Math.abs(v)}`;
 					if (v > 0) queryForDay[name] = () => `"${name}" + ${v}`;
 					if (v < 0) queryForDay[name] = () => `"${name}" - ${Math.abs(v)}`;
 				} else if (Array.isArray(v) && v.length > 0) { // ユニークインクリメント
-					const tempColumnName = uniqueTempColumnPrefix + k.replaceAll('.', columnDot);
+					const tempColumnName = uniqueTempColumnPrefix + k.replaceAll('.', columnDot) as keyof TempColumnsForUnique<T>;
 					// TODO: item をSQLエスケープ
 					const itemsForHour = v.filter(item => !logHour[tempColumnName].includes(item)).map(item => `"${item}"`);
 					const itemsForDay = v.filter(item => !logDay[tempColumnName].includes(item)).map(item => `"${item}"`);
@@ -387,10 +394,10 @@ export default abstract class Chart<T extends Schema> {
 			// bake unique count
 			for (const [k, v] of Object.entries(finalDiffs)) {
 				if (this.schema[k].uniqueIncrement) {
-					const name = columnPrefix + k.replaceAll('.', columnDot);
-					const tempColumnName = uniqueTempColumnPrefix + k.replaceAll('.', columnDot);
-					queryForHour[name] = new Set([...v, ...logHour[tempColumnName]]).size;
-					queryForDay[name] = new Set([...v, ...logDay[tempColumnName]]).size;
+					const name = columnPrefix + k.replaceAll('.', columnDot) as keyof Columns<T>;
+					const tempColumnName = uniqueTempColumnPrefix + k.replaceAll('.', columnDot) as keyof TempColumnsForUnique<T>;
+					queryForHour[name] = new Set([...(v as string[]), ...logHour[tempColumnName]]).size;
+					queryForDay[name] = new Set([...(v as string[]), ...logDay[tempColumnName]]).size;
 				}
 			}
 
@@ -399,16 +406,18 @@ export default abstract class Chart<T extends Schema> {
 			for (const [k, v] of Object.entries(this.schema)) {
 				const intersection = v.intersection;
 				if (intersection) {
-					const name = columnPrefix + k.replaceAll('.', columnDot);
+					const name = columnPrefix + k.replaceAll('.', columnDot) as keyof Columns<T>;
 					const firstKey = intersection[0];
-					const firstTempColumnName = uniqueTempColumnPrefix + firstKey.replaceAll('.', columnDot);
-					const currentValuesForHour = new Set([...(finalDiffs[firstKey] ?? []), ...logHour[firstTempColumnName]]);
-					const currentValuesForDay = new Set([...(finalDiffs[firstKey] ?? []), ...logDay[firstTempColumnName]]);
+					const firstTempColumnName = uniqueTempColumnPrefix + firstKey.replaceAll('.', columnDot) as keyof TempColumnsForUnique<T>;
+					const firstValues = finalDiffs[firstKey] as string[] | undefined;
+					const currentValuesForHour = new Set([...(firstValues ?? []), ...logHour[firstTempColumnName]]);
+					const currentValuesForDay = new Set([...(firstValues ?? []), ...logDay[firstTempColumnName]]);
 					for (let i = 1; i < intersection.length; i++) {
 						const targetKey = intersection[i];
-						const targetTempColumnName = uniqueTempColumnPrefix + targetKey.replaceAll('.', columnDot);
-						const targetValuesForHour = new Set([...(finalDiffs[targetKey] ?? []), ...logHour[targetTempColumnName]]);
-						const targetValuesForDay = new Set([...(finalDiffs[targetKey] ?? []), ...logDay[targetTempColumnName]]);
+						const targetTempColumnName = uniqueTempColumnPrefix + targetKey.replaceAll('.', columnDot) as keyof TempColumnsForUnique<T>;
+						const targetValues = finalDiffs[targetKey] as string[] | undefined;
+						const targetValuesForHour = new Set([...(targetValues ?? []), ...logHour[targetTempColumnName]]);
+						const targetValuesForDay = new Set([...(targetValues ?? []), ...logDay[targetTempColumnName]]);
 						currentValuesForHour.forEach(v => {
 							if (!targetValuesForHour.has(v)) currentValuesForHour.delete(v);
 						});
@@ -425,12 +434,12 @@ export default abstract class Chart<T extends Schema> {
 			await Promise.all([
 				this.repositoryForHour.createQueryBuilder()
 					.update()
-					.set(queryForHour)
+					.set(queryForHour as any)
 					.where('id = :id', { id: logHour.id })
 					.execute(),
 				this.repositoryForDay.createQueryBuilder()
 					.update()
-					.set(queryForDay)
+					.set(queryForDay as any)
 					.where('id = :id', { id: logDay.id })
 					.execute(),
 			]);
@@ -456,10 +465,10 @@ export default abstract class Chart<T extends Schema> {
 	public async tick(major: boolean, group: string | null = null): Promise<void> {
 		const data = major ? await this.tickMajor(group) : await this.tickMinor(group);
 
-		const columns = {} as Record<string, number>;
-		for (const [k, v] of Object.entries(data)) {
-			const name = k.replaceAll('.', columnDot);
-			columns[columnPrefix + name] = v;
+		const columns = {} as Record<keyof Columns<T>, number>;
+		for (const [k, v] of Object.entries(data) as ([keyof typeof data, number])[]) {
+			const name = columnPrefix + (k as string).replaceAll('.', columnDot) as keyof Columns<T>;
+			columns[name] = v;
 		}
 
 		if (Object.keys(columns).length === 0) {
@@ -470,12 +479,12 @@ export default abstract class Chart<T extends Schema> {
 			await Promise.all([
 				this.repositoryForHour.createQueryBuilder()
 					.update()
-					.set(columns as any)
+					.set(columns)
 					.where('id = :id', { id: logHour.id })
 					.execute(),
 				this.repositoryForDay.createQueryBuilder()
 					.update()
-					.set(columns as any)
+					.set(columns)
 					.where('id = :id', { id: logDay.id })
 					.execute(),
 			]);
@@ -501,11 +510,11 @@ export default abstract class Chart<T extends Schema> {
 		const gt = Chart.dateToTimestamp(current) - (60 * 60 * 24 * 3);
 		const lt = Chart.dateToTimestamp(current) - (60 * 60 * 24);
 
-		const columns = {} as Record<string, number>;
+		const columns = {} as Record<keyof TempColumnsForUnique<T>, []>;
 		for (const [k, v] of Object.entries(this.schema)) {
 			if (v.uniqueIncrement) {
-				const name = k.replaceAll('.', columnDot);
-				columns[uniqueTempColumnPrefix + name] = [];
+				const name = uniqueTempColumnPrefix + k.replaceAll('.', columnDot) as keyof TempColumnsForUnique<T>;
+				columns[name] = [];
 			}
 		}
 
@@ -516,13 +525,13 @@ export default abstract class Chart<T extends Schema> {
 		await Promise.all([
 			this.repositoryForHour.createQueryBuilder()
 				.update()
-				.set(columns as any)
+				.set(columns)
 				.where('date > :gt', { gt })
 				.andWhere('date < :lt', { lt })
 				.execute(),
 			this.repositoryForDay.createQueryBuilder()
 				.update()
-				.set(columns as any)
+				.set(columns)
 				.where('date > :gt', { gt })
 				.andWhere('date < :lt', { lt })
 				.execute(),
@@ -555,7 +564,7 @@ export default abstract class Chart<T extends Schema> {
 			order: {
 				date: -1,
 			},
-		});
+		}) as RawRecord<T>[];
 
 		// 要求された範囲にログがひとつもなかったら
 		if (logs.length === 0) {
@@ -567,7 +576,7 @@ export default abstract class Chart<T extends Schema> {
 				order: {
 					date: -1,
 				},
-			});
+			}) as RawRecord<T>;
 
 			if (recentLog) {
 				logs = [recentLog];
@@ -584,7 +593,7 @@ export default abstract class Chart<T extends Schema> {
 				order: {
 					date: -1,
 				},
-			});
+			}) as RawRecord<T>;
 
 			if (outdatedLog) {
 				logs.push(outdatedLog);
@@ -620,7 +629,7 @@ export default abstract class Chart<T extends Schema> {
 		 * にする
 		 */
 		for (const record of chart) {
-			for (const [k, v] of Object.entries(record)) {
+			for (const [k, v] of Object.entries(record) as ([keyof typeof record, number])[]) {
 				if (res[k]) {
 					res[k].push(v);
 				} else {