typescript - 如何设置通用约束以确保两种类型之间的公共(public)键也具有相同的值类型?

标签 typescript typescript-generics

我正在创建一个函数来将字段从一个对象复制到另一个对象,我想保证:

  • 我只能给出两个对象通用的键
  • 给定的键在两种类型中对应相同的值类型

如何实现第二个约束?这是我目前所拥有的。

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

更新

下面的答案让我更接近我想要的,但仍然不能保证给定键的值完全相同。这演示了不匹配的类型如何仍然可以编译,因为约束只保证类型存在于两个对象上somewhere,不一定针对给定的键。

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')

最佳答案

这里有一个解决方案:

type CommonKeys<S, T> = {
    [K in keyof S & keyof T]:
        [S[K], T[K]] extends [T[K], S[K]] ? K : never
}[keyof S & keyof T]

它的工作原理是首先构造一个映射对象类型,如 {s: 's', mismatch: never},然后将其映射到 's' | never 当然是

如果 [S[K], T[K]] 扩展了 [T[K], S[K]],则包含每个键 K,这会检查S[K]T[K] 是彼此的子类型,即同一类型。如果这对于您想要的过于严格,您可以将其更改为 S[K] extends T[K] 以仅检查输入值类型是否可分配给输出值类型。

Playground Link

关于typescript - 如何设置通用约束以确保两种类型之间的公共(public)键也具有相同的值类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65042182/

相关文章:

typescript - 在 TypeScript 中调用以联合作为其返回类型的函数后,如何获得 vscode 自动完成功能?

typescript ,将类型从对象映射到元组

javascript - 如何在 TypeScript 中将一种泛型类型(嵌套对象)的结构复制到另一种泛型?

javascript - Angular 中输入和跨度之间的文本绑定(bind)

javascript - 显示来自 API 的图像

angular - 如何将具有循环依赖性的 typescript 类移动到单独的文件中

typescript - 如何根据数组项的某些键定义新类型?

node.js - 如何将标准 API 错误响应制定为 Loopback 4 中的对象?

typescript - 为什么条件类型中的 "infer"会改变返回类型?

reactjs - React TSX 文件中的泛型