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

TypeScript如何从带可选属性类型的具体对象中提取实际类型

核心原因

你给DefaultServerNotes和DefaultClientNotes显式标注了Notes类型,TypeScript会执行向上类型转换,丢弃对象字面量的实际结构信息,仅保留通用的Notes类型,因此直接用typeof无法得到你需要的精确结构。


方案1:使用 satisfies 操作符(TS 4.9+ 推荐)

satisfies 操作符可以在不丢失原始类型信息的前提下,校验值是否符合目标类型约束,是目前最优的解法。

type PushTypes = "start" | "finish" 
type PullTypes = "start" | "stop"

interface Notes {
  push: Partial<Record<PushTypes, boolean>>;
  pull?: Partial<Record<PullTypes, boolean>>;
}

// 不用显式加: Notes注解,用satisfies做校验
const DefaultServerNotes = {
  push: {
    start: true,
    finish: true,
  },
} satisfies Notes;

const DefaultClientNotes = {
  push: { finish: true },
  pull: { stop: true },
} satisfies Notes;

// 此时typeof就能拿到精确结构类型
type ServerNotes = typeof DefaultServerNotes;
// 推导结果:
// {
//   push: {
//     start: boolean;
//     finish: boolean;
//   };
// }

type ClientNotes = typeof DefaultClientNotes;
// 推导结果:
// {
//   push: { finish: boolean };
//   pull: { stop: boolean };
// }

如果你的对象结构不符合Notes约束,TS会直接在satisfies位置抛出错误,不会影响类型安全。


方案2:使用泛型辅助函数(兼容低版本TS)

如果你的TS版本低于4.9无法使用satisfies,可以通过泛型工具函数实现同样的效果:

// 定义泛型辅助函数,入参必须符合Notes约束,同时返回原始参数类型
function defineNotes<T extends Notes>(notes: T): T {
  return notes;
}

const DefaultServerNotes = defineNotes({
  push: {
    start: true,
    finish: true,
  },
});

const DefaultClientNotes = defineNotes({
  push: { finish: true },
  pull: { stop: true },
});

// 效果和satisfies完全一致
type ServerNotes = typeof DefaultServerNotes;
type ClientNotes = typeof DefaultClientNotes;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.09 22:24:01