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

TypeScript如何实现类属性转换器的类型安全约束

结论

这个TypeScript类型安全需求完全可以实现,不需要使用任何any类型就能满足所有约束要求,核心实现依赖映射类型+泛型自动推断能力。

实现方案

首先改造转换器类型定义和createStorageAdapter的泛型签名,替换原有的松散any定义:

// 严格校验单个转换器合法性的辅助类型
type ValidConverter<T, C> = C extends {
  key: infer K extends keyof T;
  convertTo: (prop: T[K]) => infer R;
  convertFrom: (serialized: R) => T[K];
} ? C : never;

function createStorageAdapter<
  T,
  // 自动推断传入的转换器元组类型
  const Converters extends ReadonlyArray<{
    key: keyof T;
    convertTo: (prop: any) => any;
    convertFrom: (serialized: any) => any;
  }>
>(
  target: T,
  // 逐个校验数组中每个转换器的类型合法性
  properties: { [Index in keyof Converters]: ValidConverter<T, Converters[Index]> }
) {
  // 内部业务实现逻辑保持不变即可
}
类型约束效果

配合示例类使用时,所有类型规则会自动生效:

  • key合法性校验:如果传入的key不属于目标类的属性,TypeScript会直接抛出类型错误。
  • convertTo入参自动绑定:每个convertTo的入参类型会自动匹配对应key的原始属性类型,比如key: "todos"时,入参todos自动推断为Todo[]类型,访问不存在的属性会直接报错。
  • convertFrom入参自动绑定:每个convertFrom的入参类型会自动匹配对应convertTo的返回值类型,比如todos的convertTo返回序列化后的普通对象数组,convertFrom的入参就会自动推断为该普通对象数组类型,不会和原始Todo实例类型混淆。
  • 返回值校验:convertFrom的返回值必须和对应key的原始属性类型一致,否则会抛出类型错误。
正确使用示例
class Todo {
  name: string = "";
  isDone: boolean = false;

  toJson() {
    return {
      name: this.name,
      isDone: this.isDone
    };
  }

  static fromJson(json: ReturnType<Todo["toJson"]>) {
    const todo = new Todo();
    Object.assign(todo, json);
    return todo;
  }
}

class TodoStore {
 todos: Todo[] = [];
 someOtherProp: boolean = false;
}

const store = new TodoStore();
// 此处所有类型自动推断,不需要手动标注任何类型
const adapter = createStorageAdapter(store, [
 {
   key: "todos",
   convertTo: (todos) => todos.map(x => x.toJson()), // todos自动推断为Todo[]
   convertFrom: (todos) => todos.map(x => Todo.fromJson(x)), // todos自动推断为{name:string; isDone:boolean}[]
 },
 {
  key: "someOtherProp",
  convertTo: (prop) => prop ? 1 : 0, // prop自动推断为boolean
  convertFrom: (prop) => prop === 1 ? true : false // prop自动推断为0|1,返回值要求为boolean
 }
]);

如果出现类型不匹配的写法,比如给someOtherProp的convertFrom返回字符串、把序列化后的todos当成Todo实例调用类方法、传入不存在的key,TypeScript都会第一时间抛出编译错误,实现完整的类型安全。

注:如果使用TypeScript 5.0以下版本,可以去掉泛型签名里的const修饰符,不影响核心类型校验能力,仅字面量类型推断精度略有下降。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 17:06:57