如何让TypeScript识别合法参数必然能在不可变二维数组中找到结果?
问题:让TypeScript自动识别合法参数必然匹配数组项,无需处理undefined
首先是原代码实现:
class Constants { static readonly STATES_AND_ACRONYMS = [ ["AA", "NAME_A"], ["BB", "NAME_B"], ["CC", "NAME_C"], ["DD", "NAME_D"], ["EE", "NAME_E"], ["FF", "NAME_F"], ] as const; } type Acronym = typeof Constants.STATES_AND_ACRONYMS[number][0]; type State = typeof Constants.STATES_AND_ACRONYMS[number][1]; function getStateByAcronym(acronym : Acronym) : State{ let entry = Constants.STATES_AND_ACRONYMS.find((entry) => entry[0]==acronym) if(entry == undefined){ //impossible return Constants.STATES_AND_ACRONYMS[0][1]; } return entry[1]; } function getAcronymByState(state : State) : Acronym{ let entry = Constants.STATES_AND_ACRONYMS.find((entry) => entry[1]==state) if(entry == undefined){ //impossible return Constants.STATES_AND_ACRONYMS[0][0]; } return entry[0]; }
我定义了存储州名及其唯一缩写的不可变二维数组,基于该数组生成了Acronym和State类型。实现的两个函数分别通过缩写获取州名、通过州名获取缩写——因为参数是基于数组生成的合法类型,完全可以保证对应项一定存在,但TypeScript的find方法仍会返回可能的undefined,必须额外处理。我希望编写代码让TypeScript自动识别合法参数必然能找到匹配项,无需处理undefined,而且不想用类型断言或自定义循环来规避这个问题。
解决方案:预先生成只读映射对象
核心思路是基于原数组创建对应的只读映射对象,让TypeScript直接推断出键与值的必然对应关系,避免find方法带来的undefined问题。
class Constants { static readonly STATES_AND_ACRONYMS = [ ["AA", "NAME_A"], ["BB", "NAME_B"], ["CC", "NAME_C"], ["DD", "NAME_D"], ["EE", "NAME_E"], ["FF", "NAME_F"], ] as const; // 生成缩写到州名的只读映射 static readonly ACRONYM_TO_STATE = Object.fromEntries( Constants.STATES_AND_ACRONYMS ) as Readonly<{ [K in typeof Constants.STATES_AND_ACRONYMS[number][0]]: typeof Constants.STATES_AND_ACRONYMS[number][1] }>; // 生成州名到缩写的只读映射 static readonly STATE_TO_ACRONYM = Object.fromEntries( Constants.STATES_AND_ACRONYMS.map(([acronym, state]) => [state, acronym]) ) as Readonly<{ [K in typeof Constants.STATES_AND_ACRONYMS[number][1]]: typeof Constants.STATES_AND_ACRONYMS[number][0] }>; } // 直接从映射对象的键类型生成,更直观 type Acronym = keyof typeof Constants.ACRONYM_TO_STATE; type State = keyof typeof Constants.STATE_TO_ACRONYM; function getStateByAcronym(acronym: Acronym): State { // TypeScript可直接推断该键必然存在,无undefined风险 return Constants.ACRONYM_TO_STATE[acronym]; } function getAcronymByState(state: State): Acronym { return Constants.STATE_TO_ACRONYM[state]; }
方案说明
- 映射对象的安全性:
Object.fromEntries基于原不可变数组生成映射,配合类型断言明确键值对应关系——这个断言是完全安全的,因为原数组的缩写和州名是一一对应的唯一关系。 - TypeScript类型推断:通过对象属性访问时,TypeScript能识别到
Acronym类型的参数必然是ACRONYM_TO_STATE的合法键,因此直接返回对应值,不会出现undefined。 - 保持不可变性:用
Readonly包裹映射对象,和原数组的只读特性保持一致,避免意外修改。
内容的提问来源于stack exchange,提问作者Rafael Santiago Altoé
相关产品推荐
相关产品推荐

