我认为,您在这里有两个选择:a)为immutableAdd 返回类型添加类型断言或b)使用Record 类型。如果您可以稍微更改函数签名,我更喜欢 b),因为它更简洁/强制执行更强的输入。
a) Type assertion
export function immutableAdd<O, N extends string, T>(
object: O, name: N, value: T): O & { [key in N]: T } {
// or create separate const to assert the added property type only; like:
// const prop = { [name]: value } as { [key in N]: T }
return { ...object, [name]: value } as O & { [key in N]: T }
}
let b = immutableAdd({ a: 3 }, 'test', 'value'); // {a: number; } & { test: string; }
注意:我使用 mapped type { [key in N]: T } 作为返回类型的一部分以包含 name 属性。 { [key: N]: T }(您使用的)表示index signature,它只能有string 或number 类型。在您的情况下,N 是具有约束extends string 的类型参数,而不是string,因此会出现编译器错误。
return { ...object, [name]: value } 将解析为O & { [x: string]: T; } 类型,因为name 的确切字符串文字类型未知(我们只知道它扩展了string),因此不能分配给O & { [key in N]: T },所以我们投了。
b) Record 类型
export function immutableAdd<O, N extends string, T>(
object: O, property: Record<N,T>): O & { [key in N]: T } {
return { ...object, ...property };
}
let b = immutableAdd( { a: 3 }, { test: 'value' }); // { a: number; } & { test: string; }