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

如何约束参数为超类型且保留返回值的完整类型信息?

类型安全的代码复用解决方案

问题背景

项目中有一批类型本应继承同一接口,但由于属性名与数据库绑定无法修改,无法实现继承。需要编写一个通用函数处理这些不同类型,通过传入适配信息实现逻辑复用,同时保留原类型的完整信息(包括非尺寸/位置相关的额外属性),避免返回值丢失类型信息。

当前代码的问题是:函数返回的对象只包含适配键对应的属性,丢失了原类型的其他属性(比如Chair的color),导致类型赋值错误。

修改后的实现代码

interface Sized {
  width: number;
  height: number;
}

interface Positioned {
  x: number;
  y: number;
}

/**
 * 调整元素位置使其适配容器
 * @param element 目标元素,可包含任意额外属性
 * @param container 容器对象
 * @param elKeys 元素属性与标准尺寸/位置属性的映射
 * @param cKeys 容器属性与标准尺寸属性的映射
 * @param elementMinWidth 元素最小宽度
 * @param elementMinHeight 元素最小高度
 * @returns 调整后的原类型对象,保留所有原始属性
 */
function fitElementIntoContainer<
  Element extends Record<string, any>,
  ElKeys extends Record<keyof (Sized & Positioned), keyof Element>,
  Container extends Record<string, any>,
  CKeys extends Record<keyof Sized, keyof Container>
>(
  element: Element,
  container: Container,
  elKeys: ElKeys,
  cKeys: CKeys,
  elementMinWidth?: number,
  elementMinHeight?: number
) {
  // 复制原对象,保留所有属性
  const mutEl = { ...element };
  
  // 位置校正逻辑
  if (mutEl[elKeys.x] < 0) mutEl[elKeys.x] = 0;
  if (mutEl[elKeys.y] < 0) mutEl[elKeys.y] = 0;
  
  // 边界适配逻辑
  if (mutEl[elKeys.x] + mutEl[elKeys.width] > container[cKeys.width]) {
    mutEl[elKeys.x] = container[cKeys.width] - mutEl[elKeys.width];
  }
  if (mutEl[elKeys.y] + mutEl[elKeys.height] > container[cKeys.height]) {
    mutEl[elKeys.y] = container[cKeys.height] - mutEl[elKeys.height];
  }
  
  // 最小尺寸限制逻辑
  if (elementMinWidth !== undefined && mutEl[elKeys.width] < elementMinWidth) {
    mutEl[elKeys.width] = elementMinWidth;
  }
  if (elementMinHeight !== undefined && mutEl[elKeys.height] < elementMinHeight) {
    mutEl[elKeys.height] = elementMinHeight;
  }
  
  return mutEl;
}

interface Chair {
  chairX: number;
  chairY: number;
  chairWidth: number;
  chairHeight: number;
  color: string; // 非尺寸相关的额外属性
}

const exampleElement: Chair = {
  chairX: -3,
  chairY: 55,
  chairWidth: 40,
  chairHeight: 40,
  color: 'black'
};

const exampleContainer = {
  cW: 555,
  cH: 3300
};

const containerKeys = {
  width: "cW",
  height: "cH"
} as const;

const chairKeys = {
  x: "chairX",
  y: "chairY",
  width: "chairWidth",
  height: "chairHeight"
} as const;

// 现在可以正确赋值为Chair类型,不会丢失color属性
const fitsIntoContainer: Chair = fitElementIntoContainer(
  exampleElement,
  exampleContainer,
  chairKeys,
  containerKeys
);

关键修改点

  • 泛型参数调整:将元素类型Element作为顶层泛型,而非仅提取属性键,确保函数能识别并保留原类型的所有属性。
  • 适配键类型约束:ElKeys约束为Record<keyof (Sized & Positioned), keyof Element>,确保映射的键确实存在于原元素类型中,保证类型安全。
  • 返回值类型自动推导:由于直接返回复制的原对象,TypeScript会自动推导返回值为Element类型,完全保留原类型的所有属性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 10:54:55