TypeScript未检测到字符串赋值给字符串数组错误,如何修复?
TypeScript reducer类型检查失效问题及解决办法
我需要实现一个返回Record<string, string[]>(字符串到字符串数组的映射)的函数,但下面的代码中,reducer里把值设为字符串时,TypeScript编译居然没报错:
const parseFeatures = (featSpecs: string[]): Record<string, string[]> => featSpecs.map(f => f.split("=", 2)) .reduce((acc, [k, v]) => { // v是string类型,为什么这里能编译通过? return {...acc, [k]: v}; }, {}); console.log(parseFeatures(["foo=bar", "baz=qux,stuff,thing"])) // 下面这段代码却能正确触发编译错误:Type 'string' is not assignable to type 'string[]'. // const foo: Record<string, string[]> = {"foo": "bar"}
运行这段代码后输出的结果是:
{ "foo": "bar", "baz": "qux,stuff,thing" }
这显然不是预期的字符串到字符串数组的映射。
问题原因
这是因为reduce的初始值{}被TypeScript推断为{}类型,而函数的返回值被强制声明为Record<string, string[]>,导致TypeScript跳过了reducer内部的类型检查,直接将结果强制转换为目标类型。
解决办法
要让TypeScript对reducer进行正确的类型检查,需要明确指定累加器的类型,有两种方式:
方式1:给初始值指定类型
const parseFeatures = (featSpecs: string[]): Record<string, string[]> => featSpecs.map(f => f.split("=", 2)) .reduce((acc, [k, v]) => { // 此时会触发错误:Type 'string' is not assignable to type 'string[]' return {...acc, [k]: v}; }, {} as Record<string, string[]>); // 给初始值指定目标类型
方式2:给累加器参数指定类型
const parseFeatures = (featSpecs: string[]): Record<string, string[]> => featSpecs.map(f => f.split("=", 2)) .reduce((acc: Record<string, string[]>, [k, v]) => { // 此时会触发错误:Type 'string' is not assignable to type 'string[]' return {...acc, [k]: v}; }, {});
这样修改后,TypeScript就能正确识别出reducer中赋值类型不匹配的问题,触发预期的编译错误。
内容的提问来源于stack exchange,提问作者Nate Glenn
相关产品推荐
相关产品推荐

