如何根据对象数组的value属性定义TypeScript联合类型
解决方案
场景1:currencies数组为代码内硬编码的静态值
这种情况可以直接通过TypeScript的类型收窄能力提取value的联合类型:
// 用as const将数组内的字面量值收窄为精确的字面量类型,而不是宽的string类型 const currencies = [ { text: 'American dollars', value: 'USD' }, { text: 'Euros', value: 'EU' } ] as const // 提取所有value的联合类型 type CurrencyValue = typeof currencies[number]['value'] // 此时currency变量的类型就是 'USD' | 'EU',只能赋值为这两个值 let currency: CurrencyValue
如果需要保留对currencies数组结构的约束,避免写的时候出错,可以配合satisfies关键字:
// 定义通用的Currency结构类型 type Currency<T extends string = string> = { text: string value: T } const currencies = [ { text: 'American dollars', value: 'USD' }, { text: 'Euros', value: 'EU' } ] as const satisfies Currency[] // 提取的CurrencyValue类型依然是 'USD' | 'EU' type CurrencyValue = typeof currencies[number]['value']
场景2:currencies数组来自后端接口/数据库的动态值
TypeScript是静态类型系统,编译后类型信息会全部擦除,无法提前预知运行时才返回的后端数据结构。这种情况下需要结合运行时校验+类型守卫实现约束:
// 先定义你预期支持的合法货币值联合类型 type CurrencyValue = 'USD' | 'EU' type Currency = { text: string value: CurrencyValue } // 类型守卫:判断传入的字符串是否是合法的CurrencyValue function isCurrencyValue(value: string): value is CurrencyValue { return ['USD', 'EU'].includes(value) } // 校验后端返回的原始货币数组是否符合结构要求 function validateCurrencies(rawArr: {text: string, value: string}[]): rawArr is Currency[] { return rawArr.every(item => isCurrencyValue(item.value)) } // 调用接口获取数据后先做校验 const rawCurrencies = await fetch('/api/currencies').then(res => res.json()) if (!validateCurrencies(rawCurrencies)) { throw new Error('后端返回的货币数据不合法') } // 校验通过后rawCurrencies的类型会被收窄为Currency[] // 校验用户输入/赋值的currency是否合法 const inputValue = 'USD' // 示例值,可来自用户输入、其他逻辑返回 if (isCurrencyValue(inputValue)) { // 这里inputValue的类型已经被收窄为CurrencyValue,可以安全赋值 let currency: CurrencyValue = inputValue }
注意:如果后端返回的货币值是完全动态、无法提前枚举的,你没法在编译阶段做静态约束,只能在运行时做合法性判断。
内容的提问来源于stack exchange,提问作者opensas
相关产品推荐
相关产品推荐

