TypeScript类型交叉不生效:testFunction返回类型报错原因咨询
希望testFunction返回固定类型TReturn,同时以字符串格式返回传入的任意参数,示例调用为testFunction({ foo: "x", bar: "", baz: "" }).baz.toUpperCase();。相关代码如下:
type TArgProps = { foo: string; bar: string; }; type Dictionary = { [x: string]: string | number }; type TReturn = { page: number; sort: string; }; const transformer = (obj: any) => { let transformed: Record<string, string> = {}; for (let key in obj) { transformed[key] = obj[key].toString() }; return transformed; } const testFunction = <T extends Dictionary>( defaultProps: TArgProps & { [P in keyof T]: T[P] } = {} as any, ): TReturn & Record<keyof T, string> => { const transformed = transformer(defaultProps); return { page: 1, sort: 'abc', ...transformed }; };
但代码报错:
Type '{ page: number; sort: string; }' is not assignable to type 'TReturn & Record<keyof T, string>'.
Type '{ page: number; sort: string; }' is not assignable to type 'Record<keyof T, string>'.
请问该报错原因是什么?
类型无法窄化导致键存在性不被确认:
transformer函数返回的transformed被标注为Record<string, string>,这是一个宽泛的字符串索引类型,TypeScript无法将其自动窄化为Record<keyof T, string>。虽然逻辑上transformed包含了defaultProps的所有键,但TS的静态类型检查无法识别这一点,它只能看到展开transformed前的基础对象{page: 1, sort: 'abc'},无法确认该对象包含T的所有键,因此判定它不满足Record<keyof T, string>的约束。潜在的类型冲突风险:返回值的类型是
TReturn & Record<keyof T, string>,意味着对象的所有键既要符合TReturn的类型,又要符合Record<keyof T, string>的要求。如果T中包含page或sort键(比如传入参数里有page),就会出现page同时需要是number和string的矛盾,这也是TS对返回值类型存疑的原因之一,不过当前报错直接指向的是键存在性的问题。
内容的提问来源于stack exchange,提问作者kenneth vanmarte

