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

TypeScript映射类型:开发属性名对齐、支持类型自定义的SafeRetype泛型

需求说明

首先定义三个基础类型:

type A1 = { m1: boolean };
type A2 = { m2: number };
type B = { m1: string; m2: string };

需要实现的类型规则:

  • 新类型的属性名必须和参考类型完全对齐
  • 允许自定义属性的类型,不需要和参考类型的属性类型兼容
  • 传入的自定义类型只能包含参考类型的全部或部分属性,不允许新增参考类型不存在的属性

预期示例

符合规则的场景

// 初始实现
type SafeRetype<T, Z extends T> = { 
    [K in keyof T]?: Z[K]; 
};

// 传入Z为A1 | A2,符合规则
type C1 = SafeRetype<B, A1 | A2>;

当前初始实现存在问题:因为约束Z extends T要求Z的属性类型必须和T兼容,而A1的m1是boolean,和B的m1: string不兼容,会触发非预期的报错。

需要触发报错的场景

type D1 = { z: string };
// 传入Z为D1,新增了B不存在的属性z,需要触发类型报错
type Err = SafeRetype<B, D1>;

解决方案

问题出在两处:

  1. 原约束Z extends T过度限制了Z的属性类型,我们只需要约束Z的属性名是T的属性名的子集,不需要匹配属性类型
  2. 需要确保Z如果是联合类型,每个成员都符合属性名的约束

修正后的实现:

type SafeRetype<T, Z extends Partial<Record<keyof T, unknown>>> = {
  [K in keyof T]?: K extends keyof Z ? Z[K] : undefined;
};

效果验证

  1. 传入Z = A1 | A2时:
    • 约束校验通过:A1、A2的属性都是m1/m2,属于B的属性集合
    • 最终生成的类型为{ m1?: boolean; m2?: number },符合自定义属性类型的需求(原示例注释中写的{ m1?: string; m2?: string }属于笔误)
  2. 传入Z = D1时:
    • 约束校验失败:D1的属性z不属于B的属性集合,触发类型报错,符合预期

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.23 17:06:02