TypeScript使用联合类型创建Map时出现No overload matches this call错误
问题
在TypeScript中创建Map时,为关联的函数声明联合类型(因两个函数参数数量不同),出现No overload matches this call错误。代码如下:
type FirstFunction = (a: string, b: string, c?:string) => boolean; type SecondFunction = (a: string[], b: string, c: string) => boolean; type BothFunctions = FirstFunction | SecondFunction; const filterHandlers: Map<string, BothFunctions> = new Map([ [ "orgName", (a: string, b: string): boolean => a.toLowerCase().includes(b.toLowerCase()), ], [ "email", (a: string, b: string): boolean => a.toLowerCase().includes(b.toLowerCase()), ], [ "userName", (a: string, b: string): boolean => a.toLowerCase().includes(b.toLowerCase()), ], [ "date", (a: string, b: string): boolean => a.toLowerCase().includes(b.toLowerCase()), ], [ "phoneNumber", (a: string, b: string): boolean => a.toLowerCase().includes(b.toLowerCase()), ], [ "status", (a: string[], b: string, c: string): boolean => getUserStatus(a,b) === c, ], ]);
错误信息:
(method) String.toLowerCase(): string Converts all the alphabetic characters in a string to lowercase. No overload matches this call. Overload 1 of 4, '(iterable?: Iterable<readonly [unknown, unknown]> | null | undefined): Map<unknown, unknown>', gave the following error. Argument of type '((string | ((a: string, b: string) => boolean))[] | (string | ((a: string[], b: string, c: string) => boolean))[])[]' is not assignable to parameter of type 'Iterable<readonly [unknown, unknown]>'. The types returned by '[Symbol.iterator]().next(...)' are incompatible between these types. Type 'IteratorResult<(string | ((a: string, b: string) => boolean))[] | (string | ((a: string[], b: string, c: string) => boolean))[], any>' is not assignable to type 'IteratorResult<readonly [unknown, unknown], any>'. Type 'IteratorYieldResult<(string | ((a: string, b: string) => boolean))[] | (string | ((a: string[], b: string, c: string) => boolean))[]>' is not assignable to type 'IteratorResult<readonly [unknown, unknown], any>'. Type 'IteratorYieldResult<(string | ((a: string, b: string) => boolean))[] | (string | ((a: string[], b: string, c: string) => boolean))[]>' is not assignable to type 'IteratorYieldResult<readonly [unknown, unknown]>'. Type '(string | ((a: string, b: string) => boolean))[] | (string | ((a: string[], b: string, c: string) => boolean))[]' is not assignable to type 'readonly [unknown, unknown]'. Type '(string | ((a: string, b: string) => boolean))[]' is not assignable to type 'readonly [unknown, unknown]'. Target requires 2 element(s) but source may have fewer. Overload 2 of 4, '(entries?: readonly (readonly [string, (a: string, b: string) => boolean])[] | null | undefined): Map<string, (a: string, b: string) => boolean>', gave the following error. Type '(a: string[], b: string, c: string) => boolean' is not assignable to type '(a: string, b: string) => boolean'.ts(2769) No quick fixes available
解决方案
可以通过以下几种方法修复该错误:
方法一:显式断言每个函数为联合类型成员
TypeScript无法自动推断数组中的函数属于BothFunctions联合类型,需要手动为每个函数添加类型断言:
type FirstFunction = (a: string, b: string, c?: string) => boolean; type SecondFunction = (a: string[], b: string, c: string) => boolean; type BothFunctions = FirstFunction | SecondFunction; const filterHandlers: Map<string, BothFunctions> = new Map([ ["orgName", ((a: string, b: string): boolean => a.toLowerCase().includes(b.toLowerCase())) as BothFunctions], ["email", ((a: string, b: string): boolean => a.toLowerCase().includes(b.toLowerCase())) as BothFunctions], ["userName", ((a: string, b: string): boolean => a.toLowerCase().includes(b.toLowerCase())) as BothFunctions], ["date", ((a: string, b: string): boolean => a.toLowerCase().includes(b.toLowerCase())) as BothFunctions], ["phoneNumber", ((a: string, b: string): boolean => a.toLowerCase().includes(b.toLowerCase())) as BothFunctions], ["status", ((a: string[], b: string, c: string): boolean => getUserStatus(a,b) === c) as BothFunctions], ]);
方法二:断言整个entries数组的类型
直接对传入Map的整个条目数组断言为readonly [string, BothFunctions][],明确告知TypeScript数组的类型符合要求:
type FirstFunction = (a: string, b: string, c?: string) => boolean; type SecondFunction = (a: string[], b: string, c: string) => boolean; type BothFunctions = FirstFunction | SecondFunction; const filterHandlers: Map<string, BothFunctions> = new Map([ ["orgName", (a: string, b: string): boolean => a.toLowerCase().includes(b.toLowerCase())], ["email", (a: string, b: string): boolean => a.toLowerCase().includes(b.toLowerCase())], ["userName", (a: string, b: string): boolean => a.toLowerCase().includes(b.toLowerCase())], ["date", (a: string, b: string): boolean => a.toLowerCase().includes(b.toLowerCase())], ["phoneNumber", (a: string, b: string): boolean => a.toLowerCase().includes(b.toLowerCase())], ["status", (a: string[], b: string, c: string): boolean => getUserStatus(a,b) === c], ] as readonly [string, BothFunctions][]);
方法三:重构为兼容的单一函数类型(可选)
如果业务逻辑允许,可以将联合类型重构为一个兼容两种函数签名的类型,避免联合类型带来的推断问题:
// 定义兼容两种场景的函数类型 type FilterFunction = (a: string | string[], b: string, c?: string) => boolean; const filterHandlers: Map<string, FilterFunction> = new Map([ ["orgName", (a: string, b: string): boolean => a.toLowerCase().includes(b.toLowerCase())], ["email", (a: string, b: string): boolean => a.toLowerCase().includes(b.toLowerCase())], ["userName", (a: string, b: string): boolean => a.toLowerCase().includes(b.toLowerCase())], ["date", (a: string, b: string): boolean => a.toLowerCase().includes(b.toLowerCase())], ["phoneNumber", (a: string, b: string): boolean => a.toLowerCase().includes(b.toLowerCase())], ["status", (a: string[], b: string, c: string): boolean => getUserStatus(a,b) === c], ]);
内容的提问来源于stack exchange,提问作者Idris
相关产品推荐
相关产品推荐

