如何让TypeScript根据binanceCoins校验chainName参数合法性?
问题描述
我有一个用于类型校验的对象binanceCoins(可按需修改格式),包含500+条目,示例如下:
export const binanceCoins = { AGLD: 'ETH', STPT: 'ETH', MXN: 'FIAT_MONEY', UGX: 'FIAT_MONEY', GLM: 'ETH', RAY: 'SOL', NEAR: 'BSC' || 'NEAR' || 'BNB', AUDIO: 'ETH', ADADOWN: 'ETF', FARM: 'BSC' || 'ETH', SDG: 'FIAT_MONEY', XNO: 'NANO', DGB: 'DGB', }
同时定义了如下函数:
const topUpFromBinance = async (chainName: string, tokenName: keyof typeof binanceCoins) => {}
目前已实现让tokenName仅能传入binanceCoins的键,现需让TypeScript校验chainName:仅当它是tokenName对应binanceCoins中的有效值时才合法。例如:
tokenName为'AGLD'时,chainName只能是'ETH';tokenName为'NEAR'时,chainName可为'BSC' | 'NEAR' | 'BNB';tokenName为'SDG'时,chainName只能是'FIAT_MONEY'。
因对象条目超500条,无法逐个编写接口,请问如何实现该类型校验?是否可行?
解决方案
完全可行,核心是利用TypeScript的泛型和索引类型建立参数间的关联约束,无需手动维护每个条目类型。
步骤1:修正binanceCoins的定义
注意原代码中'BSC' || 'NEAR' || 'BNB'会被JS直接求值为'BSC',无法生成联合类型。需用字面量联合类型配合as const锁定类型:
export const binanceCoins = { AGLD: 'ETH', STPT: 'ETH', MXN: 'FIAT_MONEY', UGX: 'FIAT_MONEY', GLM: 'ETH', RAY: 'SOL', NEAR: 'BSC' as const | 'NEAR' | 'BNB', AUDIO: 'ETH', ADADOWN: 'ETF', FARM: 'BSC' as const | 'ETH', SDG: 'FIAT_MONEY', XNO: 'NANO', DGB: 'DGB', } as const;
as const的作用是让TypeScript保留所有值的字面量类型(而非自动拓宽为string),这样才能提取出精确的合法链名类型。
步骤2:用泛型重构函数
通过泛型参数T绑定tokenName的具体键类型,再通过typeof binanceCoins[T]获取对应链名的合法类型:
const topUpFromBinance = async <T extends keyof typeof binanceCoins>( chainName: typeof binanceCoins[T], tokenName: T ) => {};
效果验证
调用函数时,TypeScript会自动根据tokenName校验chainName:
- 传入
tokenName: 'AGLD',chainName仅能传'ETH'; - 传入
tokenName: 'NEAR',chainName可传'BSC'/'NEAR'/'BNB'任意一个; - 若传入不匹配组合(如
tokenName: 'SDG'却传chainName: 'ETH'),TypeScript会直接抛出类型错误。
这种方式完全适配500+条目的对象,所有类型关联由TypeScript自动推导,无需手动编写大量接口。
内容的提问来源于stack exchange,提问作者Eugene1111
相关产品推荐
相关产品推荐

