在TypeScript中具有相同键的对象参数

在TypeScript中具有相同键的对象参数,typescript,types,typescript-generics,Typescript,Types,Typescript Generics,我试图编写一个函数,它接受两个对象并返回一个合并结果。此函数与常见的合并或splat运算符之间的区别在于,此函数必须接受和返回具有相同密钥集的对象。为了简单起见,让我们只假设平面对象 我能够设计出一个版本,对输入进行编译检查。 但是,由于某些原因,它不能保护输出不被注入额外的密钥: function strictMerge<T extends Record<string, unknown>>( o1 : {[K in keyof T] : unknown}, o2

我试图编写一个函数,它接受两个对象并返回一个合并结果。此函数与常见的
合并
或splat运算符之间的区别在于,此函数必须接受和返回具有相同密钥集的对象。为了简单起见,让我们只假设平面对象

我能够设计出一个版本,对输入进行编译检查。 但是,由于某些原因,它不能保护输出不被注入额外的密钥:

function strictMerge<T extends Record<string, unknown>>(
  o1 : {[K in keyof T] : unknown},
  o2 : {[K in keyof T] : unknown},
) : {[K in keyof T] : unknown} {
  return {...o1, ...o2, bad: "bad"} // <-- no compile error :(
}

const o1 = strictMerge({}, {a: "a"})       // <-- compile error :)
const o2 = strictMerge({}, {})             // <-- no compile error :)
const o1 = strictMerge({a: "a"}, {a: "b"}) // <-- no compile error :)
函数合并(
o1:{[K in keyof T]:未知},
o2:{[K in keyof T]:未知},
):{[K in keyof T]:未知}{

返回{…o1,…o2,bad:“bad”}//编译器如何知道
bad
不是
T
中的键?还要注意,您可以只使用
(o1:T,o2:T):T
@jornsharpe我没有使用
o1:T,o2:T
版本,因为在我的实际代码中,这两种类型都是不同的(保留“相同的键”约束)。我不熟悉TS的内部工作原理,但我看不出TS应该如何仅在函数定义中确定
bad
无效。它只知道在调用站点上传递了哪些对象。当然,期望TS在这些调用站点上抛出关于
bad
的错误似乎也不太合理好问题,我不知道答案。仅供参考
strictMerge({a:“x”},{a:“x”})
也不会产生错误。以下是已知问题的列表:主要问题:编译器如何知道
bad
不是
t
中的键?请注意,您可以使用
(o1:T,o2:T):T
@jornsharpe我没有使用
o1:T,o2:T
版本,因为在我的实际代码中,这两种类型将是不同的(保持“相同的键”约束)。我不熟悉TS的内部工作原理,但我看不出TS应该如何仅在函数定义中确定
bad
无效。它只知道在调用站点上传递了哪些对象。当然,期望TS在这些调用站点上抛出关于
bad
的错误似乎也不太合理如果它确实不存在于参数中,则为。好问题,我不知道答案。仅供参考
strictMerge({a:“x”},{a:“x”})
也不会产生错误。以下是已知问题的列表:以及主要问题: