I am currently working on a function that copies fields from one object to another, and I have two main requirements:
- The key provided must be common between both objects.
- The value type corresponding to the given key should be the same in both objects.
How can I enforce the second constraint? Below is my current implementation.
function copyField<T1, T2>(input: T1, output: T2, key: keyof T1 & keyof T2) {
const keyValue = input[key]
output[key] = keyValue // How can I ensure that the key value is the same for both?
// ^ Error: Type 'T1[keyof T1 & keyof T2]' is not assignable to type 'T2[keyof T1 & keyof T2]'.
// Type 'T1' is not assignable to type 'T2'. 'T2' could be instantiated with an
// arbitrary type which could be unrelated to 'T1'.
}
type A = { field: string }
type B = { field: string }
copyField<A, B>({field: 'hello'}, {field: 'world'}, 'field')
Live example on typescriptlang.org
Update
An answer below got me closer to what I want but still doesn't guarantee that the value for the given key is exactly the same. This demonstrates how mismatched types can still compile because the constraint only guarantees that the type is present somewhere on both objects, not necessarily for the given key.
function copyField<K extends string, V>(input: {[k in K]: V}, output: {[k in K]: V}, key: K) {
const keyValue = input[key]
output[key] = keyValue
}
type A = { s: string, mismatch: string }
type B = { s: string, mismatch: number }
// ^--- these don't have the same type
const a: A = {s: 'hello', mismatch: 'hello'}
const b: B = {s: 'world', mismatch: 123}
// This compiles, but I want it to only accept 's'
copyField(a, b, 'mismatch')