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

如何为按钮样式常量对象添加类型,同时通过两类类型检查?

问题:为样式对象指定兼具理论与实际形状的TypeScript类型

我有一个表示样式集合的JavaScript对象,期望其类型符合Record<string, CSSProperties>:

const buttonStyles = {
  Primary: {
    color: 'green',
    fontSize: '18px',
  },
  Secondary: {
    color: 'grey',
  }
}

第一种错误场景

以下代码会触发类型检查错误:

function getFontSize(btnType: keyof typeof buttonStyles): string | undefined {
  // 错误:属性 'fontSize' 不存在于类型 [...]
  return buttonStyles[btnType].fontSize
}

// 这段代码能正常通过类型检查
const primaryFontSize: string = buttonStyles.Primary.fontSize

第二种错误场景

如果显式将对象类型声明为Record<string, CSSProperties>:

const buttonStyles: Record<string, CSSProperties> = {
  Primary: {
    color: 'green',
    fontSize: '18px',
  },
  Secondary: {
    color: 'grey',
  }
}

会修复上述错误,但又出现新的类型错误:

function getFontSize(btnType: keyof typeof buttonStyles): string | undefined {
  // 这段代码现在能通过类型检查
  return buttonStyles[btnType].fontSize
}

// 错误:类型“string | undefined”无法赋值给类型“string”
const primaryFontSize: string = buttonStyles.Primary.fontSize

如何为buttonStyles指定类型,使其既符合CSSProperties的“理论形状”,又保留对象自身的“实际形状”,让两段代码都能通过类型检查?


解决方案

核心思路是让TypeScript保留对象的具体结构推导,同时验证每个属性值符合CSSProperties类型,以下是几种可行方案:

方案一:使用satisfies关键字(TypeScript 4.9+ 推荐)

satisfies关键字的作用是验证对象是否符合指定类型,但不会覆盖TypeScript对对象结构的自动推导,完美满足需求:

import type { CSSProperties } from 'react'; // 根据实际环境引入CSSProperties类型

const buttonStyles = {
  Primary: {
    color: 'green',
    fontSize: '18px',
  },
  Secondary: {
    color: 'grey',
  }
} satisfies Record<string, CSSProperties>;

// 两段代码均可通过类型检查
function getFontSize(btnType: keyof typeof buttonStyles): string | undefined {
  return buttonStyles[btnType].fontSize;
}

const primaryFontSize: string = buttonStyles.Primary.fontSize;

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

如果你的TypeScript版本低于4.9,可以用泛型函数来同时实现类型约束和结构推导:

import type { CSSProperties } from 'react';

function createStyleCollection<T extends Record<string, CSSProperties>>(styles: T): T {
  return styles;
}

const buttonStyles = createStyleCollection({
  Primary: {
    color: 'green',
    fontSize: '18px',
  },
  Secondary: {
    color: 'grey',
  }
});

// 同样满足需求
function getFontSize(btnType: keyof typeof buttonStyles): string | undefined {
  return buttonStyles[btnType].fontSize;
}

const primaryFontSize: string = buttonStyles.Primary.fontSize;

方案三:手动联合类型(适合结构固定的场景)

如果样式对象的结构不会变动,也可以手动定义具体类型,再与Record<string, CSSProperties>交叉:

import type { CSSProperties } from 'react';

// 手动定义对象的具体结构类型
type ButtonStyleMap = {
  Primary: { color: string; fontSize: string };
  Secondary: { color: string };
};

// 交叉类型确保既符合具体结构,又满足CSSProperties约束
const buttonStyles: ButtonStyleMap & Record<string, CSSProperties> = {
  Primary: {
    color: 'green',
    fontSize: '18px',
  },
  Secondary: {
    color: 'grey',
  }
};

// 两段代码均可通过检查
function getFontSize(btnType: keyof typeof buttonStyles): string | undefined {
  return buttonStyles[btnType].fontSize;
}

const primaryFontSize: string = buttonStyles.Primary.fontSize;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 03:57:05