我发现以下getter函数非常有用且可重用,因为它可以获得具有此类属性的任何对象的属性key
的值。
export function keyOf<a>(value: { key: a; }) : a {
return value.key;
}
同样,我可以定义一个通用的setter函数:
export function withKey<a>(value: { key: a; }, key: a) : void {
value.key = key;
}
唯一的问题是,我需要使用修改后的void
属性返回原始对象value
,而不是返回key
。像这样:
export function withKey<b, a extends { key: b }>(value: a, key: b) : a {
value.key = key;
return value;
}
但这不是一个有效的TypeScript代码。
问题:我怎样才能获得一个类型安全的通用setter函数,它返回原始对象及其属性集?
更新:
在当前TypeScript中,类型参数之间的依赖关系是被禁止的。我相信它是为了使类型系统更简单,更快速。但是,此限制会阻止某些有用的场景,例如相关场景。有一个hack可以将类型参数之间的依赖关系转换为函数依赖关系:
export function withKey<a, b>(
value: a,
key: b,
toAssignable: (value: a) => { key: b } = function<c>(anything: c) : c {
return anything;
}
) : a {
toAssignable(value).key = key;
return value;
}
这看起来很丑陋并且改变了原始签名,但它编译并且有效。
有没有人知道更好的方法?
答案 0 :(得分:0)
我玩了一下,我只想出这个:
// === unsave approach ===
/**
* Test class
*/
class MyClassWithoutKey {
public youCanCallThis() { }
}
/**
* The setter function
*/
function withKeyUnsafe<T>(value: T, key: any) {
(<any>value).key = key;
return value;
}
// compile test
var w = withKeyUnsafe(new MyClassWithoutKey(), 2).youCanCallThis();
和此:
// === typesave approach ===
/**
* Test class
*/
class MyClassWithKey {
key: string;
public youCanCallThis() { }
}
/**
* Helper interface
*/
interface WithKey<T> {
key: T;
}
/**
* Factory function that adds type constraint
*/
function withKeyTypeSave<T>() {
/**
* The actual setter function
*/
return function <WithKeyT extends WithKey<T>>(value: WithKeyT, key: T) {
value.key = key;
return value;
}
}
// compile test -- works
withKeyTypeSave<string>()(new MyClassWithKey(), "new key").youCanCallThis();
// compile test -- fails
withKeyTypeSave<number>()(new MyClassWithKey(), "new key").youCanCallThis();
// compile test -- fails
withKeyTypeSave<string>()(new MyClassWithKey(), 3).youCanCallThis();