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

如何在TypeScript中同时实现对象类型约束与键类型推导?

问题描述

我有如下函数:

function getFeature(key: string) { ... }

我希望在代码中声明所有带fallback的可用特性:

const FEATURES = {
  'my-feature': {
    fallback: true
  },
  'another-feature': {
    fallback: false
  }
}

我想为该对象添加类型约束,确保fallback属性必须为boolean类型,因此定义了:

type FeatureMap = Record<string, { fallback: boolean}>

const FEATURES: FeatureMap = {
  'my-feature': {
    fallback: true
  },
  'another-feature': {
    fallback: false
  }
}

现在我希望getFeature函数仅接受FEATURES的键作为参数,于是尝试:

type FeatureMap = Record<string, { fallback: boolean}>

const FEATURES: FeatureMap = {
  'my-feature': {
    fallback: true
  },
  'another-feature': {
    fallback: false
  }
}

type FeatureKey = keyof typeof FEATURES;

function getFeature(key: FeatureKey) { ... }

但此时getFeature的key参数类型变为string,而非FEATURES的具体键;若移除FEATURES的FeatureMap类型标注,则能获取具体键类型,但fallback属性失去类型约束。请问是否有办法同时实现这两个需求?


解决方案

可以通过以下两种方式同时实现fallback属性的类型约束和保留FEATURES的具体键类型:

方式一:使用TypeScript 4.9+的satisfies关键字

satisfies是TypeScript 4.9新增的关键字,它可以让对象满足指定类型的约束,同时保留对象的字面量类型信息,刚好匹配你的需求:

// 定义单个特性的类型
type FeatureEntry = { fallback: boolean };
// 定义特性映射的类型
type FeatureMap = Record<string, FeatureEntry>;

// 使用satisfies确保FEATURES符合FeatureMap约束,同时保留字面量类型
const FEATURES = {
  'my-feature': { fallback: true },
  'another-feature': { fallback: false }
} satisfies FeatureMap;

// 此时FeatureKey会被推导为具体的键名联合类型:'my-feature' | 'another-feature'
type FeatureKey = keyof typeof FEATURES;

function getFeature(key: FeatureKey) { ... }

这样既保证了FEATURES中每个属性的fallback必须是boolean类型,又能让getFeature的参数只能接受FEATURES的具体键名。

方式二:泛型辅助函数(兼容旧版TypeScript)

如果你的项目使用的TypeScript版本低于4.9,可以通过泛型辅助函数来实现同样的效果:

type FeatureEntry = { fallback: boolean };

// 泛型函数接收符合约束的对象,并返回原字面量类型
function createFeatureMap<T extends Record<string, FeatureEntry>>(map: T) {
  return map;
}

// 通过辅助函数创建FEATURES,既约束类型又保留具体键名
const FEATURES = createFeatureMap({
  'my-feature': { fallback: true },
  'another-feature': { fallback: false }
});

type FeatureKey = keyof typeof FEATURES; // 类型为 'my-feature' | 'another-feature'

function getFeature(key: FeatureKey) { ... }

泛型函数createFeatureMap会检查传入的对象是否符合Record<string, FeatureEntry>的约束,同时返回对象的原始字面量类型,从而兼顾两种需求。


内容的提问来源于stack exchange,提问作者R. Groot Jebbink

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 14:02:49