Skip to content

typescript 清道夫 效果 #1

@hylarucoder

Description

@hylarucoder
 我已梳理并分批修正类型,先列出范围与结果,再给出每处的 A/B 方案与取舍说明。
  若你要我继续把 Studio 示例里残留的 any 也全部收敛,我可以继续推进。

  总体结果

  - 目标优先级:组件边界 > 外部数据入口 > 工具函数 > 错误处理 > 其他
  - 已移除/替换的 any:shared 工具、compositions 包类型与大量纸张背景组件、web
    页面与预览、Studio 配置/设计系统、部分脚本与错误处理
  - 未动的文件:生成文件(apps/web/src/routeTree.gen.ts),以及较大 Demo/3D/图
    表示例里局部 any(标注为“延期项”)

  关键改动(文件级)

  - 工具库(安全、无语义变更)
      - packages/shared/src/theme/utils.ts:1
          - pick 改为基于 unknown 的 Record 收敛;所有 API 改为 unknown + 收
            窄;normalize/derive/make 维持返回结构不变。
  - 公共类型边界(兼容增强)
      - packages/compositions/src/types.ts:1
          - CompositionDefinition 改为泛型 P extends Record<string, unknown>,
            默认 Record<string, unknown>,component: ComponentType<P>,
            defaultProps: P
      - apps/web/src/compositions/types.ts:1
          - RemotionCompositionDefinition 同 CompositionDefinition 处理
  - Web 页面与预览(移除 any/catch)
      - apps/web/src/routes/compositions-demo.tsx:1
          - library: CompositionDefinition[];form: Record<string, unknown>;
            移除 as any;主题字段通过 getThemeFrom 收敛;Player 的 component/
            inputProps 不再 any。
      - apps/web/src/components/editor/EditorPreviewPanel.tsx:1
          - playerComponent: ComponentType<Record<string, unknown>>;
            inputProps 明确为 Record<string, unknown>
      - apps/web/src/routes/__root.tsx:1
          - wheel 事件 removeEventListener 移除 as any,使用常量 wheelOptions
      - apps/web/src/polyfill.ts:1
          - File polyfill 改为 unknown 双重断言,避免 any
      - apps/web/src/routes/mcp.ts:1
          - inputSchema 使用 z.object(...),去掉 as any
      - apps/web/src/lib/render-bridge.ts:1
          - catch(e: unknown)
      - apps/web/src/lib/studio-bundle.ts:1
          - config/chConfig 使用最小 Webpack-like 类型与 unknown,移除 any
  - Studio 设计系统与配置(移除 any)
      - apps/studio/src/design-system/index.ts:1
          - utils.getColor 安全取值;responsive<T> 泛型;mergeStyles 使
            用 CSSProperties
      - apps/studio/src/design-system/tokens/spacing.ts:1
          - getComponentSpacing 去除 as any,返回 unknown 或原对象
      - apps/studio/src/design-system/layout/positioning.ts:1
          - flex.row/column 的 align 参数使用 CSSProperties["alignItems"],移
            除 as any
      - apps/studio/remotion.config.ts:1
          - 与 web 一致的 WebpackLikeConfig + unknown,移除 any
  - Studio 类型与注册(边界更稳)
      - apps/studio/src/types.ts:1
          - ClipMetadata.defaultProps: Record<string, unknown>;schema:
            unknown
      - apps/studio/src/types/slideComposition.ts:1
          - 移除 props/组件 any,统一为 Record<string, unknown>;补齐常用属性
            而不设 any 索引;SlideElementProps.clipComponent 使用受限类型
      - apps/studio/src/lib/clip-registry.ts:1
          - defaultProps 断言为 Record<string, unknown>
      - apps/studio/src/utils/clipRegistry.ts:252
          - (clip as { defaultProps?: Record<string,
            unknown> }).defaultProps,替换 as any
  - compositions 纸张背景类组件(全面移除 any)
      - 所有 paper-*.tsx(如 paper-warp/paper-smoke-ring/... 共 20+)
          - props 统一为 { fit?: string } & Record<string, unknown>;展开
            props;fit 以 typeof props.fit === 'string' 收敛;去掉 ...(props
            as any)、fit as any
  - compositions 其他组件/定义
      - image-primitive/component.tsx:44
          - objectPosition 使用 React.CSSProperties["objectPosition"]
      - image-primitive/definition.ts:12、code-primitive/definition.ts:12、
        text-primitive/definition.ts:12、group-primitive/definition.ts:12、
        rectangle-primitive/definition.ts:12
          - defaultProps 使用 Partial<typeof defaults> 替代 as any
      - text-primitive/component.tsx:42,46
          - 去除 fontWeight/textAlign 的 any
      - editor/editor-canvas-export/component.tsx:17-55
          - computeTransform 直接使用 item;组合定义/组件使用
            CompositionDefinition 与 ComponentType<Record<string, unknown>>;
            compositionProps 安全展开,移除多处 any
      - packages/compositions/src/compositions/library/code-animation/theme-
        registry.ts:5
          - highlight?: unknown
  - 主题注册(web)
      - apps/web/src/compositions/library/code-animation/theme-registry.ts:4
          - highlight?: unknown
  - 错误处理
      - scripts/test-remotion-bundle.ts / scripts/build-thumbnail.ts / apps/
        web/src/lib/render-bridge.ts / Studio 字幕组件等
          - catch(e: unknown),并保留原日志语义
  - Studio 音频可视化
      - apps/studio/src/composition/captions/audiowave/component.tsx
          - (window as any) 改为 window as unknown as { Audio,
            AudioContext },移除 any

  已保留不动(生成或大示例,延期项)

  - apps/web/src/routeTree.gen.ts: 生成文件(注释已说明不可修改)。
  - 三维/图表/大型模板中与三方库紧耦合的 any(如 gsap/THREE/Intl 的快速
    断言):
      - apps/studio/src/projects/P080-llm-cheat/...(大量 THREE.Material 相
        关)
      - apps/studio/src/scenes-templates/...(gsap.utils 与自定义节点数
        据 any)
      - apps/studio/src/composition/text-animation/rotating-
        text(Intl.Segmenter)
      - 如需继续,我可以以 wrapper/最小 d.ts 补丁方式逐步替换。

  — — —

  工作流与审阅清单

  1. 审阅(Review)

  - 显式 any(原因)
      - 组件 props/ComponentType<any>:历史默认宽松,便于动态渲染。
      - 工具函数参数/返回 any:图省事,类型信息缺失(如 theme utils)。
      - Webpack 覆盖 config: any:第三方类型复杂/未引入类型。
      - 运行时 env/浏览器 API:window/Audio/Intl 等未按环境分型。
      - 生成代码:路由树生成器使用 as any(工具生成限制)。
  - 隐式 any(原因)
      - catch(e) 未设 unknown:tsconfig 未强制 useUnknownInCatchVariables。
      - Map/Record 异构访问:reduce 链式取值未做守卫。
  - 风险标注
      - 组件边界:高(跨包/渲染器传 props)。
      - 工具函数:中(被多处调用)。
      - 第三方类型缺失:中(Webpack/CodeHike/Audio)。
      - 错误处理:低(已标准化 unknown)。

  2. 分组(Attribution)

  - 来源数据:主题 JSON、Studio 项目数据(EditorItem/Clip metadata)
  - 组件边界:CompositionDefinition、RemotionCompositionDefinition、纸张背景组
    件 props
  - 工具函数:shared/theme/utils.ts、design-system utils
  - 第三方库:Webpack 配置、codehike/mdx、window.Audio/AudioContext、
    Intl.Segmenter、THREE、gsap
  - 错误处理:各处 catch(e)

  3. 方案(A/B)

  - 组件边界(CompositionDefinition 与组件 props)
      - A:CompositionDefinition 引入泛型 P 默认 Record<string, unknown>;组件
        统一 ComponentType<P>;defaultProps:P
          - 优点:与现有调用点兼容,推断稳定;无运行时变化。
          - 缺点:个别地方需要补 Partial<...> 帮助推断。
      - B:为每个组件定义精确 Props 类型并在导出 Definition 时强约束
          - 优点:最强约束与提示;缺点:工程量大,易受变更影响。
      - 取舍:A(已实施),部分 Definition 用 Partial<defaults> 兜底推断。
  - 工具函数(theme utils)
      - A:unknown + 收窄(isRecord + pick),返回保持原结构
          - 优点:安全,调用方无需改动。
      - B:显式主题 JSON 类型(详尽结构)
          - 优点:强类型;缺点:维护成本高。
      - 取舍:A(已实施)。
  - Webpack/CodeHike 配置
      - A:最小 WebpackLikeConfig + unknown,并按使用位置做窄化
      - B:引入 @types/webpack 或完整 bundler 类型
      - 取舍:A(已实施),保持零依赖。
  - 运行时 API(window.Audio/AudioContext)
      - A:unknown -> 结构断言对象 { Audio, AudioContext }
      - B:ambient d.ts 声明全局
      - 取舍:A(已实施),不污染全局类型。
  - 错误处理
      - A:catch(e: unknown) + 原样日志/传递
      - B:自定义 AppError 类型并转换
      - 取舍:A(已实施),保持语义不变。

  4. 取舍(Decision)

  - 已全面采用 A 案(unknown + 收窄、泛型与约束)以最小风险替代 any,运行时语
    义不变,外部 API 兼容不破坏。
  - 分步策略:已将高优先级(跨包类型/工具/错误处理/页面)收敛;Studio 大型示例
    与三方对象流转(THREE/gsap/Intl)列为后续阶段。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions