Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
通过兼容的属性类型约束泛型的typescript_Typescript - Fatal编程技术网

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

通过兼容的属性类型约束泛型的typescript,typescript,Typescript,我正在编写一个函数,用另一个对象中的其他属性更新一个对象中的属性 像 函数compareAndUpdate(目标:T,源:S,目标键:keyof T,源键:keyof S):布尔值{ //一些加工 target[targetKey]=source[sourceKey];//此行给出错误信息 //再加工一些 } 我知道我可以通过使用来修复错误。如果希望它们相等,您可以使用相同的类型: function compareAndUpdate<T>(target: T, source: T

我正在编写一个函数,用另一个对象中的其他属性更新一个对象中的属性

函数compareAndUpdate(目标:T,源:S,目标键:keyof T,源键:keyof S):布尔值{
//一些加工
target[targetKey]=source[sourceKey];//此行给出错误信息
//再加工一些
}

我知道我可以通过使用

来修复错误。如果希望它们相等,您可以使用相同的类型:

function compareAndUpdate<T>(target: T, source: T, targrtKey: keyof T, sourceKey: keyof T): boolean { return true; }
当您使用时,如果有人试图将属性放置在目标上,则会出现错误,而属性不是
T

function compareAndUpdate<T extends S, S>(target: T, source: S, targrtKey: keyof T, sourceKey: keyof S): boolean { return true; }
//Valid
compareAndUpdate({ test: "S"}, { test: "DD" }, "test", "test")
compareAndUpdate({ test: "S", bla : 0}, { test: "DD" }, "test", "test")
//Invalied, bla does not exist on T
compareAndUpdate({ test: "S"}, { test: "DD", bla : 0 }, "test", "test")
为了简单起见,我使用对象文字,但如果类中包含字段,它也可以用于类:

class Dog {
  name: string;
  bark(): void{}
}
// OK
compareAndUpdate(new Dog(), {name: "" }, "name", "name");
// NOK
compareAndUpdate(new Dog(), {isAGodBoy: "" }, "name", "name");

事实上,你可以这样做。以下是方法:

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;
}

这对你有用吗?

这个错误是有道理的。编译器给出以下错误,因为它不知道可以推断出哪种类型。可以编写比较和更新函数,以便在检测到更改时真正更新对象并返回新的更改…@giespapen我没有错误问题。我想保证,当传递不兼容的属性键时,编译器应该进行捕获。
target
source
都是不同类型的
T
S
可能有或可能没有同名的礼节,但是
T
可以有一个属性,其类型与
S
@AbdulKareem中的其他属性相同。不幸的是,我看不到用两个完全不相关的类型来实现这一点的方法。无论如何,我会在github上为此提出一个问题,我认为这不足以保证github的问题;看到一个非常有趣的解决方案,我不认为这是可能的,
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;
}
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