TypeScript合并字符串/字符串与字符串/谓词Map报错问题
问题分析与解决
问题场景
我们有三个Map:
- 字符串到字符串的映射:
const strToStr = new Map<string, string>([ ['foo', 'foo'], ['bar', 'qux'], ]);
- 字符串到布尔谓词函数的映射:
const strToFnc = new Map<string, (_: string) => boolean>([ ['baz', (_: string) => true], ['buz', (_: string) => false], ]);
- 用于存储谓词函数的目标Map:
const predicates = new Map<string, (_: string) => boolean>();
处理strToStr时,通过生成谓词函数的方式添加到predicates可以正常运行:
strToStr.forEach((k) => predicates.set(k, (_) => (k == strToStr.get(k))));
但处理strToFnc时执行以下代码却触发TypeScript类型错误:
strToFnc.forEach((k) => predicates.set(k, strToFnc.get(k)));
报错信息:
temp.ts:11:40 - error TS2345: Argument of type '(_: string) => boolean' is not assignable to parameter of type 'string'. 11 strToFnc.forEach((k) => predicates.set(k, strToFnc.get(k))); ~ temp.ts:11:56 - error TS2345: Argument of type '(_: string) => boolean' is not assignable to parameter of type 'string'. 11 strToFnc.forEach((k) => predicates.set(k, strToFnc.get(k))); ~ Found 2 errors in the same file, starting at: temp.ts:11
明明strToFnc.get(...)返回的是谓词函数,为何会报错?
问题原因
核心错误是搞反了Map.forEach的回调参数顺序:
- Map的
forEach方法回调函数的第一个参数是Map中当前项的value,第二个参数才是当前项的key。
在strToStr.forEach((k) => ...)中,虽然参数名叫k,但它实际是strToStr里的字符串value,刚好和predicates.set需要的key类型匹配(都是string),所以碰巧没报错。
但到了strToFnc.forEach((k) => ...)时,这个k实际是strToFnc里的谓词函数(value类型),而predicates.set的第一个参数需要string类型的key,把函数传进去自然触发类型不匹配的错误;同时你调用strToFnc.get(k)时,k是函数类型,而get需要string类型的key,这又触发第二个类型错误。
解决方法
修正forEach的参数顺序,明确区分value和key:
// 直接使用forEach拿到的value和key,无需再调用get strToFnc.forEach((predicateFn, key) => predicates.set(key, predicateFn));
这样key是string类型,predicateFn是(_: string) => boolean类型,完全符合predicates.set的参数要求,类型错误会消失。
内容的提问来源于stack exchange,提问作者Patrick Bucher
相关产品推荐
相关产品推荐

