如何让依赖GitHubRepositoryFilter键类型的filterValue参数实现类型安全?
如何让GitHubRepositoryFilter对应过滤函数的filterValue参数实现类型安全?
现有如下TypeScript代码,定义了GitHubRepositoryFilter类型及对应的repositoryFilters过滤函数集合,其中filterValue参数当前为any类型。请问是否可以让该filterValue参数实现类型安全,使其类型与GitHubRepositoryFilter对应键的类型相匹配?
export type GitHubRepositoryFilter = { withName?: string; withWorkflowRuns?: boolean; }; export const repositoryFilters: Record< keyof GitHubRepositoryFilter, (repository: GitHubRepository, filterValue: any) => boolean > = { withWorkflowRuns: ({ hasWorkFLows }, filterValue) => hasWorkFLows === filterValue, withName: ({ name }, filterValue) => name.toLowerCase().includes(filterValue.toLowerCase()), };
完全可以做到,核心思路是用TypeScript的映射类型,让每个过滤函数的filterValue参数类型严格匹配GitHubRepositoryFilter对应键的类型,替换掉原来的any。具体实现步骤如下:
首先补全GitHubRepository的定义(原代码未给出,假设结构如下):
type GitHubRepository = { name: string; hasWorkFLows: boolean; };
然后修改过滤函数集合的类型定义,用映射类型绑定对应键的类型:
export type GitHubRepositoryFilter = { withName?: string; withWorkflowRuns?: boolean; }; // 定义映射类型,每个键对应的函数参数filterValue严格匹配原类型 type RepositoryFilterFunctions = { [K in keyof GitHubRepositoryFilter]: ( repository: GitHubRepository, filterValue: GitHubRepositoryFilter[K] ) => boolean; }; // 给repositoryFilters指定这个映射类型,实现类型安全 export const repositoryFilters: RepositoryFilterFunctions = { withWorkflowRuns: ({ hasWorkFLows }, filterValue) => hasWorkFLows === filterValue, withName: ({ name }, filterValue) => name.toLowerCase().includes(filterValue.toLowerCase()), };
关键说明
[K in keyof GitHubRepositoryFilter]会遍历GitHubRepositoryFilter的所有键,为每个键生成专属的函数类型GitHubRepositoryFilter[K]会取当前键K在原类型里的具体类型,比如withName对应string,withWorkflowRuns对应boolean,彻底避免any的松散类型- 现在如果给过滤函数传错类型的值,TypeScript会直接报错,比如给
withWorkflowRuns传字符串,编辑器立刻会提示类型不匹配
可选优化:处理可选参数
如果你的过滤逻辑需要处理filterValue为undefined的情况(因为原类型里的键都是可选的),可以直接保留GitHubRepositoryFilter[K]的类型;如果只需要处理非空值,可以用NonNullable<GitHubRepositoryFilter[K]>来约束:
type RepositoryFilterFunctions = { [K in keyof GitHubRepositoryFilter]: ( repository: GitHubRepository, filterValue: NonNullable<GitHubRepositoryFilter[K]> ) => boolean; };
内容的提问来源于stack exchange,提问作者Ben Keil
相关产品推荐
相关产品推荐

