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

TypeScript中如何通过Wrapper属性关联对应姐妹接口类型?

实现仅传入包装类型属性即可约束对应姐妹接口参数的泛型函数

核心思路

要实现仅传入包装实例的属性就自动约束第二个参数,关键在于从属性值反向推断出原接口类型和属性键,再通过预定义的接口映射表找到对应的姐妹接口属性类型。

完整实现代码

// 1. 定义接口对的映射表,支持多组接口扩展
interface InterfacePairMap {
  A: B;
  B: A; // 可选:如果需要双向关联的话
}

// 2. 包装类型定义(和你原代码一致)
type WrapperType<T> = { extraProp: string } & T;

// 3. 从包装类型的属性值中提取原接口和属性键的信息
type ExtractWrapperInfo<V> = 
  V extends WrapperType<infer T>[infer P] 
  ? { BaseInterface: T; PropKey: P } 
  : never;

// 4. 获取对应姐妹接口的同键属性类型
type RelatedPropType<V> = 
  ExtractWrapperInfo<V> extends { BaseInterface: infer T; PropKey: infer P } 
  ? P extends keyof InterfacePairMap[T] 
    ? InterfacePairMap[T][P] 
    : never 
  : never;

// 5. 目标泛型函数
declare function doSomething<V>(propValue: V, relatedProp: RelatedPropType<V>): void;

// ------------------------------
// 测试示例
// ------------------------------
interface A {
  foo: string;
  bar: number;
}

interface B {
  foo: { id: string };
  bar: boolean;
}

// 创建包装实例
const x: WrapperType<A> = {
  extraProp: "Hello",
  foo: "World",
  bar: 10,
};

// 正确用法:第二个参数自动约束为B['foo']类型
doSomething(x.foo, { id: "test" });

// 错误用法:类型不匹配,TypeScript会抛出错误
// doSomething(x.foo, "wrong");

// 测试bar属性
doSomething(x.bar, true); // 正确,对应B['bar']的boolean类型
// doSomething(x.bar, "wrong"); // 错误

关键部分说明

  • InterfacePairMap:用映射表管理所有接口对,后续新增接口对只需在这里添加条目,扩展性极强。
  • ExtractWrapperInfo:通过条件类型的infer关键字,从传入的属性值(比如x.foo)反向推断出它属于哪个原接口(A)以及对应的属性键(foo)。
  • RelatedPropType:结合映射表,找到原接口对应的姐妹接口,再取出同键的属性类型,作为第二个参数的约束。
  • doSomething函数:泛型参数V捕获属性值的类型,自动推导第二个参数的类型约束,完全不需要传入包装实例或键名。

扩展支持多组接口

如果需要新增另一组接口对,比如C和D,只需:

  1. 定义接口C和D
  2. 在InterfacePairMap中添加映射:
interface C {
  baz: Date;
}

interface D {
  baz: string;
}

interface InterfacePairMap {
  A: B;
  B: A;
  C: D;
  D: C;
}

之后函数就能自动支持这组接口的属性约束。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 21:53:19