如何在TypeScript中正确定义ES6对象/字典的类型?
解决方案
方案1:优先使用ES6原生Map(最适配需求的最优解)
ES6的Map类型的TS定义完美覆盖你的两种使用场景:
- 调用
map.get(key)方法时,返回类型自动为User | undefined,符合访问不存在key的实际运行逻辑 - 调用
map.values()遍历的时候,返回的元素类型就是纯User,不会携带多余的undefined类型
示例代码:
type User = { id: string, name: string } const usersMap = new Map<string, User>() // 取值场景,返回 User | undefined,类型安全 const user = usersMap.get('user_id_that_doesnt_exist') // 遍历场景,元素为纯User类型,无需额外判断 Array.from(usersMap.values()).map(user => { // 此处user的类型自动推导为User })
方案2:坚持使用普通对象作为字典
如果业务要求必须用普通对象实现字典,可按以下方式处理:
- 索引签名保留
User | undefined保证取值时的类型安全 - 遍历时通过类型守卫收窄类型,消除undefined的类型干扰:
type User = { id: string, name: string } const usersDict: { [key: string]: User | undefined } = {} // 取值场景,返回 User | undefined,符合预期 const user = usersDict['user_id_that_doesnt_exist'] // 遍历场景,用类型守卫过滤掉undefined const validUsers = Object.values(usersDict).filter((u): u is User => typeof u !== 'undefined') validUsers.map(user => { // 此处user的类型自动推导为User })
原理解释
TS本身无法静态追踪普通对象的动态键值对赋值情况,无法区分“主动赋值的undefined”和“访问不存在的key返回的undefined”,所以给索引签名加| undefined是类型安全的必要前提,遍历的时候只需要加一次类型守卫即可规避多余的类型判断成本。
内容的提问来源于stack exchange,提问作者Arch1tect
相关产品推荐
相关产品推荐

