forked from FoundKeyGang/FoundKey
refactor: fix types
This commit is contained in:
parent
8d568d533b
commit
51aad804d6
1 changed files with 72 additions and 63 deletions
|
@ -17,8 +17,27 @@ const columnPrefix = '___' as const;
|
||||||
const uniqueTempColumnPrefix = 'unique_temp___' as const;
|
const uniqueTempColumnPrefix = 'unique_temp___' as const;
|
||||||
const columnDot = '_' 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 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> = {
|
type RawRecord<S extends Schema> = {
|
||||||
id: number;
|
id: number;
|
||||||
|
|
||||||
|
@ -31,11 +50,7 @@ type RawRecord<S extends Schema> = {
|
||||||
* 集計日時のUnixタイムスタンプ(秒)
|
* 集計日時のUnixタイムスタンプ(秒)
|
||||||
*/
|
*/
|
||||||
date: number;
|
date: number;
|
||||||
} & {
|
} & TempColumnsForUnique<S> & Columns<S>;
|
||||||
[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;
|
|
||||||
};
|
|
||||||
|
|
||||||
const camelToSnake = (str: string): string => {
|
const camelToSnake = (str: string): string => {
|
||||||
return str.replace(/([A-Z])/g, s => '_' + s.charAt(0).toLowerCase());
|
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));
|
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> = {
|
type Commit<S extends Schema> = {
|
||||||
[K in keyof S]?: S[K]['uniqueIncrement'] extends true ? string[] : number;
|
[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>;
|
diff: Commit<T>;
|
||||||
group: string | null;
|
group: string | null;
|
||||||
}[] = [];
|
}[] = [];
|
||||||
protected repositoryForHour: Repository<RawRecord<T>>;
|
// ↓にしたいけどfindOneとかで型エラーになる
|
||||||
protected repositoryForDay: Repository<RawRecord<T>>;
|
//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削除などアプリケーション側で感知できない変動によるズレの修正用)
|
* 1日に一回程度実行されれば良いような計算処理を入れる(主にCASCADE削除などアプリケーション側で感知できない変動によるズレの修正用)
|
||||||
|
@ -196,23 +203,23 @@ export default abstract class Chart<T extends Schema> {
|
||||||
this.schema = schema;
|
this.schema = schema;
|
||||||
|
|
||||||
const { hour, day } = Chart.schemaToEntity(name, schema, grouped);
|
const { hour, day } = Chart.schemaToEntity(name, schema, grouped);
|
||||||
this.repositoryForHour = getRepository<RawRecord<T>>(hour);
|
this.repositoryForHour = getRepository<{ id: number; group?: string | null; date: number; }>(hour);
|
||||||
this.repositoryForDay = getRepository<RawRecord<T>>(day);
|
this.repositoryForDay = getRepository<{ id: number; group?: string | null; date: number; }>(day);
|
||||||
}
|
}
|
||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
private convertRawRecord(x: RawRecord<T>): KVs<T> {
|
private convertRawRecord(x: RawRecord<T>): KVs<T> {
|
||||||
const kvs = {} as KVs<T>;
|
const kvs = {} as Record<string, number>;
|
||||||
for (const k of Object.keys(x).filter(k => k.startsWith(columnPrefix))) {
|
for (const k of Object.keys(x).filter((k) => k.startsWith(columnPrefix)) as (keyof Columns<T>)[]) {
|
||||||
kvs[k.substr(columnPrefix.length).split(columnDot).join('.')] = x[k];
|
kvs[(k as string).substr(columnPrefix.length).split(columnDot).join('.')] = x[k];
|
||||||
}
|
}
|
||||||
return kvs;
|
return kvs as KVs<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
private getNewLog(latest: KVs<T> | null): KVs<T> {
|
private getNewLog(latest: KVs<T> | null): KVs<T> {
|
||||||
const log = {} as Record<keyof T, number>;
|
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) {
|
if (v.accumulate && latest) {
|
||||||
log[k] = latest[k];
|
log[k] = latest[k];
|
||||||
} else {
|
} else {
|
||||||
|
@ -235,7 +242,7 @@ export default abstract class Chart<T extends Schema> {
|
||||||
order: {
|
order: {
|
||||||
date: -1,
|
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({
|
const currentLog = await repository.findOne({
|
||||||
date: Chart.dateToTimestamp(current),
|
date: Chart.dateToTimestamp(current),
|
||||||
...(group ? { group: group } : {}),
|
...(group ? { group: group } : {}),
|
||||||
});
|
}) as RawRecord<T>;
|
||||||
|
|
||||||
// ログがあればそれを返して終了
|
// ログがあればそれを返して終了
|
||||||
if (currentLog != null) {
|
if (currentLog != null) {
|
||||||
|
@ -299,7 +306,7 @@ export default abstract class Chart<T extends Schema> {
|
||||||
const currentLog = await repository.findOne({
|
const currentLog = await repository.findOne({
|
||||||
date: date,
|
date: date,
|
||||||
...(group ? { group: group } : {}),
|
...(group ? { group: group } : {}),
|
||||||
});
|
}) as RawRecord<T>;
|
||||||
|
|
||||||
// ログがあればそれを返して終了
|
// ログがあればそれを返して終了
|
||||||
if (currentLog != null) return currentLog;
|
if (currentLog != null) return currentLog;
|
||||||
|
@ -315,7 +322,7 @@ export default abstract class Chart<T extends Schema> {
|
||||||
date: date,
|
date: date,
|
||||||
...(group ? { group: group } : {}),
|
...(group ? { group: group } : {}),
|
||||||
...columns,
|
...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`);
|
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 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 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)) {
|
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') {
|
if (typeof finalDiffs[k] === 'number') {
|
||||||
(finalDiffs[k] as number) += v as number;
|
(finalDiffs[k] as number) += v as number;
|
||||||
} else {
|
} 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 queryForHour: Record<keyof RawRecord<T>, number | (() => string)> = {} as any;
|
||||||
const queryForDay: Record<string, number | (() => string)> = {};
|
const queryForDay: Record<keyof RawRecord<T>, number | (() => string)> = {} as any;
|
||||||
for (const [k, v] of Object.entries(finalDiffs)) {
|
for (const [k, v] of Object.entries(finalDiffs)) {
|
||||||
if (typeof v === 'number') {
|
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}" + ${v}`;
|
||||||
if (v < 0) queryForHour[name] = () => `"${name}" - ${Math.abs(v)}`;
|
if (v < 0) queryForHour[name] = () => `"${name}" - ${Math.abs(v)}`;
|
||||||
if (v > 0) queryForDay[name] = () => `"${name}" + ${v}`;
|
if (v > 0) queryForDay[name] = () => `"${name}" + ${v}`;
|
||||||
if (v < 0) queryForDay[name] = () => `"${name}" - ${Math.abs(v)}`;
|
if (v < 0) queryForDay[name] = () => `"${name}" - ${Math.abs(v)}`;
|
||||||
} else if (Array.isArray(v) && v.length > 0) { // ユニークインクリメント
|
} 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エスケープ
|
// TODO: item をSQLエスケープ
|
||||||
const itemsForHour = v.filter(item => !logHour[tempColumnName].includes(item)).map(item => `"${item}"`);
|
const itemsForHour = v.filter(item => !logHour[tempColumnName].includes(item)).map(item => `"${item}"`);
|
||||||
const itemsForDay = v.filter(item => !logDay[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
|
// bake unique count
|
||||||
for (const [k, v] of Object.entries(finalDiffs)) {
|
for (const [k, v] of Object.entries(finalDiffs)) {
|
||||||
if (this.schema[k].uniqueIncrement) {
|
if (this.schema[k].uniqueIncrement) {
|
||||||
const name = columnPrefix + k.replaceAll('.', columnDot);
|
const name = columnPrefix + k.replaceAll('.', columnDot) as keyof Columns<T>;
|
||||||
const tempColumnName = uniqueTempColumnPrefix + k.replaceAll('.', columnDot);
|
const tempColumnName = uniqueTempColumnPrefix + k.replaceAll('.', columnDot) as keyof TempColumnsForUnique<T>;
|
||||||
queryForHour[name] = new Set([...v, ...logHour[tempColumnName]]).size;
|
queryForHour[name] = new Set([...(v as string[]), ...logHour[tempColumnName]]).size;
|
||||||
queryForDay[name] = new Set([...v, ...logDay[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)) {
|
for (const [k, v] of Object.entries(this.schema)) {
|
||||||
const intersection = v.intersection;
|
const intersection = v.intersection;
|
||||||
if (intersection) {
|
if (intersection) {
|
||||||
const name = columnPrefix + k.replaceAll('.', columnDot);
|
const name = columnPrefix + k.replaceAll('.', columnDot) as keyof Columns<T>;
|
||||||
const firstKey = intersection[0];
|
const firstKey = intersection[0];
|
||||||
const firstTempColumnName = uniqueTempColumnPrefix + firstKey.replaceAll('.', columnDot);
|
const firstTempColumnName = uniqueTempColumnPrefix + firstKey.replaceAll('.', columnDot) as keyof TempColumnsForUnique<T>;
|
||||||
const currentValuesForHour = new Set([...(finalDiffs[firstKey] ?? []), ...logHour[firstTempColumnName]]);
|
const firstValues = finalDiffs[firstKey] as string[] | undefined;
|
||||||
const currentValuesForDay = new Set([...(finalDiffs[firstKey] ?? []), ...logDay[firstTempColumnName]]);
|
const currentValuesForHour = new Set([...(firstValues ?? []), ...logHour[firstTempColumnName]]);
|
||||||
|
const currentValuesForDay = new Set([...(firstValues ?? []), ...logDay[firstTempColumnName]]);
|
||||||
for (let i = 1; i < intersection.length; i++) {
|
for (let i = 1; i < intersection.length; i++) {
|
||||||
const targetKey = intersection[i];
|
const targetKey = intersection[i];
|
||||||
const targetTempColumnName = uniqueTempColumnPrefix + targetKey.replaceAll('.', columnDot);
|
const targetTempColumnName = uniqueTempColumnPrefix + targetKey.replaceAll('.', columnDot) as keyof TempColumnsForUnique<T>;
|
||||||
const targetValuesForHour = new Set([...(finalDiffs[targetKey] ?? []), ...logHour[targetTempColumnName]]);
|
const targetValues = finalDiffs[targetKey] as string[] | undefined;
|
||||||
const targetValuesForDay = new Set([...(finalDiffs[targetKey] ?? []), ...logDay[targetTempColumnName]]);
|
const targetValuesForHour = new Set([...(targetValues ?? []), ...logHour[targetTempColumnName]]);
|
||||||
|
const targetValuesForDay = new Set([...(targetValues ?? []), ...logDay[targetTempColumnName]]);
|
||||||
currentValuesForHour.forEach(v => {
|
currentValuesForHour.forEach(v => {
|
||||||
if (!targetValuesForHour.has(v)) currentValuesForHour.delete(v);
|
if (!targetValuesForHour.has(v)) currentValuesForHour.delete(v);
|
||||||
});
|
});
|
||||||
|
@ -425,12 +434,12 @@ export default abstract class Chart<T extends Schema> {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this.repositoryForHour.createQueryBuilder()
|
this.repositoryForHour.createQueryBuilder()
|
||||||
.update()
|
.update()
|
||||||
.set(queryForHour)
|
.set(queryForHour as any)
|
||||||
.where('id = :id', { id: logHour.id })
|
.where('id = :id', { id: logHour.id })
|
||||||
.execute(),
|
.execute(),
|
||||||
this.repositoryForDay.createQueryBuilder()
|
this.repositoryForDay.createQueryBuilder()
|
||||||
.update()
|
.update()
|
||||||
.set(queryForDay)
|
.set(queryForDay as any)
|
||||||
.where('id = :id', { id: logDay.id })
|
.where('id = :id', { id: logDay.id })
|
||||||
.execute(),
|
.execute(),
|
||||||
]);
|
]);
|
||||||
|
@ -456,10 +465,10 @@ export default abstract class Chart<T extends Schema> {
|
||||||
public async tick(major: boolean, group: string | null = null): Promise<void> {
|
public async tick(major: boolean, group: string | null = null): Promise<void> {
|
||||||
const data = major ? await this.tickMajor(group) : await this.tickMinor(group);
|
const data = major ? await this.tickMajor(group) : await this.tickMinor(group);
|
||||||
|
|
||||||
const columns = {} as Record<string, number>;
|
const columns = {} as Record<keyof Columns<T>, number>;
|
||||||
for (const [k, v] of Object.entries(data)) {
|
for (const [k, v] of Object.entries(data) as ([keyof typeof data, number])[]) {
|
||||||
const name = k.replaceAll('.', columnDot);
|
const name = columnPrefix + (k as string).replaceAll('.', columnDot) as keyof Columns<T>;
|
||||||
columns[columnPrefix + name] = v;
|
columns[name] = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Object.keys(columns).length === 0) {
|
if (Object.keys(columns).length === 0) {
|
||||||
|
@ -470,12 +479,12 @@ export default abstract class Chart<T extends Schema> {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this.repositoryForHour.createQueryBuilder()
|
this.repositoryForHour.createQueryBuilder()
|
||||||
.update()
|
.update()
|
||||||
.set(columns as any)
|
.set(columns)
|
||||||
.where('id = :id', { id: logHour.id })
|
.where('id = :id', { id: logHour.id })
|
||||||
.execute(),
|
.execute(),
|
||||||
this.repositoryForDay.createQueryBuilder()
|
this.repositoryForDay.createQueryBuilder()
|
||||||
.update()
|
.update()
|
||||||
.set(columns as any)
|
.set(columns)
|
||||||
.where('id = :id', { id: logDay.id })
|
.where('id = :id', { id: logDay.id })
|
||||||
.execute(),
|
.execute(),
|
||||||
]);
|
]);
|
||||||
|
@ -501,11 +510,11 @@ export default abstract class Chart<T extends Schema> {
|
||||||
const gt = Chart.dateToTimestamp(current) - (60 * 60 * 24 * 3);
|
const gt = Chart.dateToTimestamp(current) - (60 * 60 * 24 * 3);
|
||||||
const lt = Chart.dateToTimestamp(current) - (60 * 60 * 24);
|
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)) {
|
for (const [k, v] of Object.entries(this.schema)) {
|
||||||
if (v.uniqueIncrement) {
|
if (v.uniqueIncrement) {
|
||||||
const name = k.replaceAll('.', columnDot);
|
const name = uniqueTempColumnPrefix + k.replaceAll('.', columnDot) as keyof TempColumnsForUnique<T>;
|
||||||
columns[uniqueTempColumnPrefix + name] = [];
|
columns[name] = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -516,13 +525,13 @@ export default abstract class Chart<T extends Schema> {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this.repositoryForHour.createQueryBuilder()
|
this.repositoryForHour.createQueryBuilder()
|
||||||
.update()
|
.update()
|
||||||
.set(columns as any)
|
.set(columns)
|
||||||
.where('date > :gt', { gt })
|
.where('date > :gt', { gt })
|
||||||
.andWhere('date < :lt', { lt })
|
.andWhere('date < :lt', { lt })
|
||||||
.execute(),
|
.execute(),
|
||||||
this.repositoryForDay.createQueryBuilder()
|
this.repositoryForDay.createQueryBuilder()
|
||||||
.update()
|
.update()
|
||||||
.set(columns as any)
|
.set(columns)
|
||||||
.where('date > :gt', { gt })
|
.where('date > :gt', { gt })
|
||||||
.andWhere('date < :lt', { lt })
|
.andWhere('date < :lt', { lt })
|
||||||
.execute(),
|
.execute(),
|
||||||
|
@ -555,7 +564,7 @@ export default abstract class Chart<T extends Schema> {
|
||||||
order: {
|
order: {
|
||||||
date: -1,
|
date: -1,
|
||||||
},
|
},
|
||||||
});
|
}) as RawRecord<T>[];
|
||||||
|
|
||||||
// 要求された範囲にログがひとつもなかったら
|
// 要求された範囲にログがひとつもなかったら
|
||||||
if (logs.length === 0) {
|
if (logs.length === 0) {
|
||||||
|
@ -567,7 +576,7 @@ export default abstract class Chart<T extends Schema> {
|
||||||
order: {
|
order: {
|
||||||
date: -1,
|
date: -1,
|
||||||
},
|
},
|
||||||
});
|
}) as RawRecord<T>;
|
||||||
|
|
||||||
if (recentLog) {
|
if (recentLog) {
|
||||||
logs = [recentLog];
|
logs = [recentLog];
|
||||||
|
@ -584,7 +593,7 @@ export default abstract class Chart<T extends Schema> {
|
||||||
order: {
|
order: {
|
||||||
date: -1,
|
date: -1,
|
||||||
},
|
},
|
||||||
});
|
}) as RawRecord<T>;
|
||||||
|
|
||||||
if (outdatedLog) {
|
if (outdatedLog) {
|
||||||
logs.push(outdatedLog);
|
logs.push(outdatedLog);
|
||||||
|
@ -620,7 +629,7 @@ export default abstract class Chart<T extends Schema> {
|
||||||
* にする
|
* にする
|
||||||
*/
|
*/
|
||||||
for (const record of chart) {
|
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]) {
|
if (res[k]) {
|
||||||
res[k].push(v);
|
res[k].push(v);
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue