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

TypeScript:如何提取Model泛型属性内部类型并保留其他属性?

问题原因与解决方案

核心原因

你的代码出现普通属性类型被推断为unknown的问题,大概率是因为Model类型的泛型参数设置了默认值unknown(比如定义为type Model<T = unknown> = { /* ... */ })。

当TypeScript执行T[P] extends Model<infer R>的条件判断时,如果Model有默认泛型参数,它会自动将默认值unknown填充进去,尝试判断普通类型(比如number、string)是否能匹配Model<unknown>。如果Model的结构允许这种宽松匹配(比如包含可选属性、或者是兼容基础类型的联合类型),就会触发条件分支,导致infer R被推断为unknown,最终普通属性的类型被替换成unknown。

解决方案

根据Model的定义场景,有三种常见的解决方式:

方式1:移除Model的泛型默认参数

如果Model不需要默认类型参数,直接去掉默认值,强制必须传入具体类型:

// 修正Model的定义,去掉默认参数
type Model<T> = { data: T };

type MyType<T> = {
  [P in keyof T]: T[P] extends Model<infer R> ? R : T[P];
};

// 测试示例
type Test = MyType<{ name: string; age: Model<number> }>;
// 结果:{ name: string; age: number }

方式2:给Model添加唯一标识,严格区分类型

如果必须保留Model的泛型默认参数,可以给Model添加一个唯一的标识属性,确保只有真正的Model实例才会被匹配:

// 添加__isModel标识属性
type Model<T = unknown> = { __isModel: true; data: T };

type MyType<T> = {
  [P in keyof T]: T[P] extends { __isModel: true; data: infer R } ? R : T[P];
};

// 测试示例
type Test = MyType<{ name: string; age: Model<number> }>;
// 结果:{ name: string; age: number }

方式3:双重条件判断,避免宽松匹配

如果不想修改Model的定义,可以通过双重条件判断确保精确匹配:

type Model<T = unknown> = { data: T };

type MyType<T> = {
  [P in keyof T]: T[P] extends Model<infer R> 
    ? (Model<R> extends T[P] ? R : T[P]) 
    : T[P];
};

// 测试示例
type Test = MyType<{ name: string; age: Model<number> }>;
// 结果:{ name: string; age: number }

这里的双重判断会先验证T[P]是否能赋值给Model<infer R>,再反向验证Model<R>是否能赋值给T[P],排除因默认参数导致的宽松匹配情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 22:10:19