如何在Javascript/Typescript中实现直接返回值且支持嵌套属性的对象
实现方案
完全可以实现你要的效果,下面给出3种不需要修改原型、实现成本低的可行方案:
方案1:字符串包装对象实现(最推荐,完全符合预期效果)
JS中String构造函数可以生成一个包装对象,本身在参与字符串运算、打印时会自动拆箱返回基础字符串值,同时我们可以给这个对象挂载自定义的变体属性,完全满足你的需求。
JS 实现代码
function createColor(mainColor, variants = {}) { // 生成字符串包装对象,默认取值就是主色值 const colorInstance = new String(mainColor) // 挂载所有变体属性 Object.assign(colorInstance, variants) return colorInstance } // 调用生成你要的color对象 const color = createColor('red', { light: 'lightcoral', dark: 'darkred' })
效果验证
console.log(color) // 输出:red console.log(color.light) // 输出:lightcoral console.log(color.dark) // 输出:darkred // 直接作为字符串使用也完全兼容 document.body.style.color = color // 生效,值为red
注意事项
该方案生成的对象typeof返回值为object,如果有严格判断typeof x === 'string'的场景,手动调用String(color)转为基础字符串即可,绝大多数场景下都会自动拆箱无需额外处理。
方案2:TypeScript 适配版本
如果是TS环境,可以配合类型定义实现完全的类型提示:
// 定义变体属性的类型,可自行扩展 type ColorVariants = { light?: string dark?: string contrastText?: string } & Record<string, string | undefined> // 最终Color类型等价于字符串+所有变体属性的集合 type Color<T extends ColorVariants> = string & T function createColor<T extends ColorVariants>(main: string, variants: T): Color<T> { const color = new String(main) as unknown as Color<T> Object.assign(color, variants) return color } // 使用时会自动获得类型提示 const color = createColor('red', { light: 'lightcoral', dark: 'darkred' })
方案3:Proxy实现(适合需要动态逻辑的场景)
如果你不希望使用包装对象,也可以用Proxy实现,适合需要动态计算变体值的场景:
function createColor(mainColor, variants = {}) { const target = { _main: mainColor, ...variants } return new Proxy(target, { get(target, prop) { // 处理字符串转换场景 if (prop === Symbol.toPrimitive || prop === 'valueOf' || prop === 'toString') { return () => target._main } return Reflect.get(target, prop) } }) }
该方案的缺点是console.log(color)会直接打印代理对象而非主色值,仅在字符串上下文(比如模板字符串拼接、赋值给字符串类型变量)时会自动返回主色值。
内容的提问来源于stack exchange,提问作者Jonatas Amaral
相关产品推荐
相关产品推荐

