【发布时间】:2019-08-12 18:22:21
【问题描述】:
我正在尝试定义一个函数,该函数在给定名称的对象上交换两个属性的值,但我希望编译器检查类型兼容性(或至少检查两个属性是否具有相同的类型):
function swap<T, TKey1 extends keyof T, TKey2 extends keyof T>(obj: T, key1: TKey1, key2: TKey2): void{
let temp = obj[key1];
obj[key1] = obj[key2];
obj[key2] = temp;
}
let obj = {
a: 1,
b: 2,
c: ""
}
swap(obj, "a", "b"); // good, both are numbers
swap(obj, "a", "c"); // should not compile, swapping number with string
我得到了以下结果,但它需要 obj 传递两次。
function swap<T,
TKey1 extends keyof T,
TKey2 extends keyof T,
TIn extends { [p in TKey1|TKey2]: T[TKey1] } >(_:T, obj: TIn, key1: TKey1, key2: TKey2): void{
let temp = <any>obj[key1];
obj[key1] = <any>obj[key2];
obj[key2] = temp;
}
let obj = {
a: 1,
b: 2,
c: ""
}
swap(obj, obj, "a", "b"); // good, both are numbers
swap(obj, obj, "a", "c"); // error, as expected
另外,如果我返回一个函数,我可以使用条件类型来达到预期的结果,但是很容易忘记第二次调用。
function swap<T,
TKey1 extends keyof T,
TKey2 extends keyof T>(obj: T, key1: TKey1, key2: TKey2):
T[TKey1] extends T[TKey2] ? T[TKey2] extends T[TKey1]
? () => void
: never : never {
return <any>(() => {
let temp = <any>obj[key1];
obj[key1] = <any>obj[key2];
obj[key2] = temp;
});
}
let obj = {
a: 1,
b: 2,
c: ""
}
swap(obj, "a", "b")(); // good, both are numbers
swap(obj, "a", "c")(); // error, as expected
上面的例子可以简化吗?我可以提供某种类型而不是 never 来指示类型系统错误吗?
附:我知道 [obj.a, obj.b] = [obj.b, obj.a]; ,但想避免它。
【问题讨论】:
标签: typescript types swap