typescript通过兼容的属性类型约束泛型

Abd*_*eem 3 typescript

我正在编写一个函数,它property在一个对象中与property另一个对象中的其他对象进行更新

喜欢

function compareAndUpdate<T, S>(target: T, source: S, targrtKey: keyof T, sourceKey: keyof S): boolean {
    // some processing
    target[targrtKey] = source[sourceKey]; // this line gives error 

    // some more processing

}
Run Code Online (Sandbox Code Playgroud)

我知道我可以通过使用来修复错误 <any>

target并且source是不同类型的.T并且S可能有也可能没有相同名称的礼仪,但T可以拥有与其他财产类型相同的财产S

有没有办法保证,typeof target[targrtKey] === typeof source[sourceKey]以便编译器在传递不兼容的属性键时捕获错误.

编辑:此处提交上游功能请求

jca*_*alz 7

事实上,你可以做到这一点.这是如何做:

function compareAndUpdate<T, TK extends keyof T, SK extends string, S extends Record<SK,T[TK]>>(target: T, source: S, targetKey: TK, sourceKey: SK): boolean {
    // some processing
    target[targetKey] = source[sourceKey]; // okay
    return true;
}
Run Code Online (Sandbox Code Playgroud)

让我们打开那个声明:

  • T 是目标的类型
  • TK是目标键的类型(因此需要扩展keyof T).请注意,T[TK]是目标的类型值,该键.
  • SK是源键的类型(因此需要扩展string)
  • S是源的类型,需要SK作为键,并且从该键获得的任何值都需要分配给T[TK]. Record<SK,T[TK]>是具有类型的键和类型SK值的类型T[TK].所以,当S extends Record<SK,T[TK]>我们在说,我们希望S成为任何类型的地方S[SK]是一样的T[TK].

我们来试试吧:

interface Person {
  name: string;
  age: number;
}
const person: Person = { name: 'Stephen King', age: 69 };

interface Book {
  title: string;
  authorName: string;
}
const book: Book = { title: 'The Running Man', authorName: 'Richard Bachman' };

compareAndUpdate(book, person, 'authorName', 'name'); // okay
compareAndUpdate(book, person, 'authorName', 'age');  // error, number not assignable to string
compareAndUpdate(person, book, 'authorName', 'name'); // error, 'name' property not found
Run Code Online (Sandbox Code Playgroud)

那对你有用吗?