TypeScript用string索引类型报错且禁用any类型该如何解决?
问题原因
你定义的PopularPosts['posts']对象只有固定4个字面量类型的合法key:food/vacations/travel/music,而用来索引的postType是宽泛的string类型,TS无法确认这个字符串一定属于合法key范围,因此抛出索引类型不匹配的错误。
合法解决方案(均不需要声明any)
方案1:限定
postType的类型为合法key联合(最推荐,类型安全最高)
直接把postType的类型定义为keyof PopularPosts['posts'],这个类型会自动推导为'food' | 'vacations' | 'travel' | 'music'的联合类型,从根源上限定postType只能是合法值。
如果postType来自用户输入/接口返回等不可控场景,额外加一层类型守卫校验即可:// 先定义合法key类型 type PostTypeKey = keyof PopularPosts['posts'] // 类型守卫函数,判断入参是不是合法key function isValidPostType(key: string): key is PostTypeKey { return ['food', 'vacations', 'travel', 'music'].includes(key) } // 使用时先校验 if (isValidPostType(postType)) { // 这里TS会自动识别postType是合法key,不会报错 const targetPosts = posts[postType].posts }方案2:给对象添加字符串索引签名(适合后续可能新增其他分类的场景)
如果你确定所有字符串key对应的value都是CategoryPosts类型,可以直接修改类型定义,给posts对象加索引签名:export type PopularPosts = { posts: { // 字符串索引签名,声明所有string类型key的value都是CategoryPosts [key: string]: CategoryPosts; food: CategoryPosts; vacations: CategoryPosts; travel: CategoryPosts; music: CategoryPosts; } }改完之后直接用任意string索引posts对象都会返回
CategoryPosts类型,不会报错,且类型安全度远高于any。方案3:使用类型断言(适合确定postType一定是合法key的场景)
如果你100%确定运行时postType一定是四个合法key之一,可以临时用类型断言告诉TS你的判断:const targetPosts = posts[postType as keyof PopularPosts['posts']].posts注意:该方案相当于你主动跳过TS的类型校验,需要自行确保运行时值的合法性,不推荐高频使用。
内容的提问来源于stack exchange,提问作者p_waves
相关产品推荐
相关产品推荐

