I'm creating a function to copy fields from one object to another and I'd like to guarantee:
- I can only give a key that is common between both objects
- the given key corresponds to the same value type in both types
How can I implement the second constraint? Here's what I have so far.
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')