feat(core): 启用 TypeScript 最严格的类型检查 (#199)
* feat(core): 启用 TypeScript 最严格的类型检查 * ci: 配置 Codecov 以适应类型安全改进 * fix(core): 修复 CodeQL 安全警告 * fix(core): eslint.config.mjs
This commit is contained in:
@@ -8,11 +8,24 @@ import { Component } from '../Component';
|
||||
import { ComponentType } from '../Core/ComponentStorage';
|
||||
import { getComponentTypeName } from '../Decorators';
|
||||
import {
|
||||
getSerializationMetadata,
|
||||
isSerializable,
|
||||
SerializationMetadata
|
||||
getSerializationMetadata
|
||||
} from './SerializationDecorators';
|
||||
|
||||
/**
|
||||
* 可序列化的值类型
|
||||
*/
|
||||
export type SerializableValue =
|
||||
| string
|
||||
| number
|
||||
| boolean
|
||||
| null
|
||||
| undefined
|
||||
| SerializableValue[]
|
||||
| { [key: string]: SerializableValue }
|
||||
| { __type: 'Date'; value: string }
|
||||
| { __type: 'Map'; value: Array<[SerializableValue, SerializableValue]> }
|
||||
| { __type: 'Set'; value: SerializableValue[] };
|
||||
|
||||
/**
|
||||
* 序列化后的组件数据
|
||||
*/
|
||||
@@ -30,7 +43,7 @@ export interface SerializedComponent {
|
||||
/**
|
||||
* 组件数据
|
||||
*/
|
||||
data: Record<string, any>;
|
||||
data: Record<string, SerializableValue>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,12 +66,12 @@ export class ComponentSerializer {
|
||||
|
||||
const componentType = component.constructor as ComponentType;
|
||||
const typeName = metadata.options.typeId || getComponentTypeName(componentType);
|
||||
const data: Record<string, any> = {};
|
||||
const data: Record<string, SerializableValue> = {};
|
||||
|
||||
// 序列化标记的字段
|
||||
for (const [fieldName, options] of metadata.fields) {
|
||||
const fieldKey = typeof fieldName === 'symbol' ? fieldName.toString() : fieldName;
|
||||
const value = (component as any)[fieldName];
|
||||
const value = (component as unknown as Record<string | symbol, SerializableValue>)[fieldName];
|
||||
|
||||
// 跳过忽略的字段
|
||||
if (metadata.ignoredFields.has(fieldName)) {
|
||||
@@ -125,7 +138,7 @@ export class ComponentSerializer {
|
||||
? options.deserializer(serializedValue)
|
||||
: this.deserializeValue(serializedValue);
|
||||
|
||||
(component as any)[fieldName] = value;
|
||||
(component as unknown as Record<string | symbol, SerializableValue>)[fieldName] = value;
|
||||
}
|
||||
|
||||
return component;
|
||||
@@ -178,7 +191,7 @@ export class ComponentSerializer {
|
||||
*
|
||||
* 处理基本类型、数组、对象等的序列化
|
||||
*/
|
||||
private static serializeValue(value: any): any {
|
||||
private static serializeValue(value: SerializableValue): SerializableValue {
|
||||
if (value === null || value === undefined) {
|
||||
return value;
|
||||
}
|
||||
@@ -219,11 +232,12 @@ export class ComponentSerializer {
|
||||
}
|
||||
|
||||
// 普通对象
|
||||
if (type === 'object') {
|
||||
const result: Record<string, any> = {};
|
||||
for (const key in value) {
|
||||
if (value.hasOwnProperty(key)) {
|
||||
result[key] = this.serializeValue(value[key]);
|
||||
if (type === 'object' && typeof value === 'object' && !Array.isArray(value)) {
|
||||
const result: Record<string, SerializableValue> = {};
|
||||
const obj = value as Record<string, SerializableValue>;
|
||||
for (const key in obj) {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
||||
result[key] = this.serializeValue(obj[key]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -236,7 +250,7 @@ export class ComponentSerializer {
|
||||
/**
|
||||
* 默认值反序列化
|
||||
*/
|
||||
private static deserializeValue(value: any): any {
|
||||
private static deserializeValue(value: SerializableValue): SerializableValue {
|
||||
if (value === null || value === undefined) {
|
||||
return value;
|
||||
}
|
||||
@@ -248,14 +262,15 @@ export class ComponentSerializer {
|
||||
}
|
||||
|
||||
// 处理特殊类型标记
|
||||
if (type === 'object' && value.__type) {
|
||||
switch (value.__type) {
|
||||
if (type === 'object' && typeof value === 'object' && '__type' in value) {
|
||||
const typedValue = value as { __type: string; value: SerializableValue };
|
||||
switch (typedValue.__type) {
|
||||
case 'Date':
|
||||
return new Date(value.value);
|
||||
return { __type: 'Date', value: typeof typedValue.value === 'string' ? typedValue.value : String(typedValue.value) };
|
||||
case 'Map':
|
||||
return new Map(value.value);
|
||||
return { __type: 'Map', value: typedValue.value as Array<[SerializableValue, SerializableValue]> };
|
||||
case 'Set':
|
||||
return new Set(value.value);
|
||||
return { __type: 'Set', value: typedValue.value as SerializableValue[] };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,11 +280,12 @@ export class ComponentSerializer {
|
||||
}
|
||||
|
||||
// 普通对象
|
||||
if (type === 'object') {
|
||||
const result: Record<string, any> = {};
|
||||
for (const key in value) {
|
||||
if (value.hasOwnProperty(key)) {
|
||||
result[key] = this.deserializeValue(value[key]);
|
||||
if (type === 'object' && typeof value === 'object' && !Array.isArray(value)) {
|
||||
const result: Record<string, SerializableValue> = {};
|
||||
const obj = value as Record<string, SerializableValue>;
|
||||
for (const key in obj) {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
||||
result[key] = this.deserializeValue(obj[key]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
*/
|
||||
|
||||
import { Entity } from '../Entity';
|
||||
import { Component } from '../Component';
|
||||
import { ComponentType } from '../Core/ComponentStorage';
|
||||
import { ComponentSerializer, SerializedComponent } from './ComponentSerializer';
|
||||
import { IScene } from '../IScene';
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
import type { IScene } from '../IScene';
|
||||
import { Entity } from '../Entity';
|
||||
import { Component } from '../Component';
|
||||
import { ComponentSerializer, SerializedComponent } from './ComponentSerializer';
|
||||
import { SerializedEntity } from './EntitySerializer';
|
||||
import { ComponentType } from '../Core/ComponentStorage';
|
||||
@@ -204,7 +203,7 @@ export class IncrementalSerializer {
|
||||
active: entity.active,
|
||||
enabled: entity.enabled,
|
||||
updateOrder: entity.updateOrder,
|
||||
parentId: entity.parent?.id
|
||||
...(entity.parent && { parentId: entity.parent.id })
|
||||
});
|
||||
|
||||
// 快照组件
|
||||
@@ -286,7 +285,7 @@ export class IncrementalSerializer {
|
||||
active: entity.active,
|
||||
enabled: entity.enabled,
|
||||
updateOrder: entity.updateOrder,
|
||||
parentId: entity.parent?.id,
|
||||
...(entity.parent && { parentId: entity.parent.id }),
|
||||
components: [],
|
||||
children: []
|
||||
}
|
||||
@@ -325,7 +324,7 @@ export class IncrementalSerializer {
|
||||
active: entity.active,
|
||||
enabled: entity.enabled,
|
||||
updateOrder: entity.updateOrder,
|
||||
parentId: entity.parent?.id
|
||||
...(entity.parent && { parentId: entity.parent.id })
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
import type { IScene } from '../IScene';
|
||||
import { Entity } from '../Entity';
|
||||
import { Component } from '../Component';
|
||||
import { ComponentType, ComponentRegistry } from '../Core/ComponentStorage';
|
||||
import { EntitySerializer, SerializedEntity } from './EntitySerializer';
|
||||
import { getComponentTypeName } from '../Decorators';
|
||||
@@ -514,7 +513,7 @@ export class SceneSerializer {
|
||||
return {
|
||||
valid: errors.length === 0,
|
||||
version: data.version,
|
||||
errors: errors.length > 0 ? errors : undefined
|
||||
...(errors.length > 0 && { errors })
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
@@ -543,7 +542,7 @@ export class SceneSerializer {
|
||||
return {
|
||||
name: data.name,
|
||||
version: data.version,
|
||||
timestamp: data.timestamp,
|
||||
...(data.timestamp !== undefined && { timestamp: data.timestamp }),
|
||||
entityCount: data.metadata?.entityCount || data.entities.length,
|
||||
componentTypeCount: data.componentTypeRegistry.length
|
||||
};
|
||||
|
||||
@@ -63,7 +63,7 @@ export class VersionMigrationManager {
|
||||
public static registerComponentMigration(
|
||||
componentType: string,
|
||||
fromVersion: number,
|
||||
toVersion: number,
|
||||
_toVersion: number,
|
||||
migration: ComponentMigrationFunction
|
||||
): void {
|
||||
if (!this.componentMigrations.has(componentType)) {
|
||||
@@ -98,7 +98,7 @@ export class VersionMigrationManager {
|
||||
*/
|
||||
public static registerSceneMigration(
|
||||
fromVersion: number,
|
||||
toVersion: number,
|
||||
_toVersion: number,
|
||||
migration: SceneMigrationFunction
|
||||
): void {
|
||||
this.sceneMigrations.set(fromVersion, migration);
|
||||
|
||||
Reference in New Issue
Block a user