You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否在TypeScript中精准定义结构化可克隆类型?

结构化克隆兼容的TypeScript类型定义与问题分析

我需要定义一套可通过结构化克隆算法传递的TypeScript类型集合,用于约束那些需要通过postMessage、structuredClone传递,或通过history.pushState、IndexedDB持久化的数据,避免触发DataCloneError。目前我主要在IndexedDB场景中使用这个类型。

奇怪的是TypeScript并没有在Web API家族中内置该类型——虽然它不属于ECMAScript规范,但属于HTML规范,而且Node、Deno、Bun等环境都支持。可能因为普通开发者对这类API的需求较少,所以官方没有内置。

初步类型定义

type TypedArray =
  | Int8Array
  | Uint8Array
  | Uint8ClampedArray
  | Int16Array
  | Uint16Array
  | Int32Array
  | Uint32Array
  | Float32Array
  | Float64Array
  | BigInt64Array
  | BigUint64Array;

type StructureClonableError =
  | Error
  | EvalError
  | RangeError
  | ReferenceError
  | SyntaxError
  | TypeError
  | URIError;

/** 兼容的Web API类型 */
type WebClonableObjects =
  // | AudioData
  | Blob
  // | CropTarget
  | CryptoKey
  | DOMException
  | DOMMatrix
  | DOMMatrixReadOnly
  | DOMPoint
  | DOMPointReadOnly
  | DOMQuad
  | DOMRect
  | DOMRectReadOnly
  | File
  | FileList
  | FileSystemDirectoryHandle
  | FileSystemFileHandle
  | FileSystemHandle
  // | GPUCompilationInfo
  // | GPUCompilationMessage
  | ImageBitmap
  | ImageData
  | RTCCertificate
  | VideoFrame;

/** 结构化克隆兼容类型 */
export type StructureClonable =
  | string
  | number
  | boolean
  | bigint
  | null
  | undefined
  | StructureClonable[]
  | readonly StructureClonable[]
  | { [key: string]: StructureClonable }
  | Set<StructureClonable>
  | Map<StructureClonable, StructureClonable>
  | Date
  | ArrayBuffer
  | StructureClonableError
  | RegExp
  | TypedArray
  | WebClonableObjects;

类型校验案例

我写了一个测试函数来验证类型约束效果:

function hasToBeStructureClonable(value: StructureClonable) { worker.postMessage(value) }
// 简写
const htbsc = hasToBeStructureClonable

// 正常校验场景(符合预期)
htbsc({ foo: "bar" })                             // 合法值,校验通过 ✅
htbsc(document)                                   // 非法值,校验拦截 ✅
htbsc({ element: document.createElement("div") }) // 非法值,校验拦截 ✅
htbsc(() => {})                                   // 非法值,校验拦截 ✅
htbsc({ [Symbol()]: "symbols are not ok" })       // 非法值,校验拦截 ✅
htbsc(new Date)                                   // 合法值,校验通过 ✅
htbsc(new class {})                               // 非法值,校验拦截 ✅
htbsc(new Error)                                  // 合法值,校验通过 ✅

// 存在漏洞的场景(不符合预期)
htbsc(Object.assign(new Date, { document }))      // 非法值,但校验通过 ❌
// 自定义继承内置类的实例无法被序列化
htbsc(new class MyError extends Error {})         // 非法值,但校验通过 ❌
htbsc(Object.assign([1,2,3], { document }))       // 非法值,但校验通过 ❌
htbsc({ get foo() { return "bar" } })             // getter会被丢弃,校验无提示 ⚠️

无法解决的局限性

结构化克隆算法会忽略属性描述符、移除写入限制,还会丢弃getter/setter函数,导致克隆后的对象结构和原对象不一致。由于TypeScript无法追踪属性是存储值还是通过getter定义,这类问题目前没有办法通过类型约束解决。

内容的提问来源于stack exchange,提问作者Link0

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 11:37:20