我想强烈键入属性名称
myMethod(model => model.userId);
public myMethod(model: () => any) {
//Must print "userId"
}
我已经知道这行不通,因为JavaScript会评估userId。
在C#中很容易做到:
Get string property name from expression
Retrieving Property name from lambda expression
可以在TypeScript / JavaScript中实现吗?
答案 0 :(得分:3)
与C#不同,您可以按属性名称动态访问属性,因此可以这样做:
myMethod(model, "userId")
现在关于打字稿的很酷的事情是该字符串实际上可以是类型安全的:
function myMethod<T, K extends keyof T>(model: T, key: K) {
const value = model[key];
//...
}
如果您真的想像在C#中那样做类似的事情(不要!),只需执行以下操作:
function myMethod(model: () => any) {
const key = model.toString().split(".")[1];
//...
}
答案 1 :(得分:3)
如果我理解您的要求,您想检查一个获取属性的箭头函数,并返回它返回的属性的 name 吗?对于像JavaScript这样的弱/动态类型化的语言,这听起来像是个坏主意,任何理智的人都应该大喊大叫。尽管如此,假设我要么发疯,要么被逼迫,这是我将如何尝试在编译为ES2015的TypeScript 2.9中做到这一点:
type ValueOf<T> = T[keyof T];
function evilMagic<T, V extends T[keyof T]>(
f: (x: T)=>V
): ValueOf<{[K in keyof T]: T[K] extends V ? K : never}>;
function evilMagic(f:(x: any)=>any): keyof any {
var p = new Proxy({}, {
get(target, prop) { return prop }
})
return f(p);
}
函数evilMagic
使用一个获取属性的函数,并尝试返回它返回的属性的名称。输出的 type 很难解释,但是基本上它是keyof T
的子集,其中T
是属性获取函数期望的参数。函数的实现使用Proxy对象p
,其作用类似于某些对象,其值始终与其键相同。也就是说,p.foo
是"foo"
,p.bar
是"bar"
,而p[10]
是"10"
。在p
上调用属性获取器,然后abracadabra,您将获得属性的名称。
以下是其用法示例:
interface Person {
name: string;
age: number;
numberOfLimbs: number;
}
const m = evilMagic((x: Person) => x.age); // typed as "age"|"numberOfLimbs";
console.log(m); // "age"
在编译时,TypeScript只能告诉m
是"age"
或"numberOfLimbs"
之一,因为它只能看到回调函数返回了number
。在运行时,您将按预期获得"age"
。
这整个事情使我感到恐惧,我觉得写起来很不整洁。一个期望某个类型值的函数在交给该代理时可能会做各种疯狂的事情。我不愿意想到这样的代码,尽管它可能是有用的调试工具,但最终会以任何用于生产的方式结束。请告诉我您仅将其用于调试工具!
无论如何,希望能有所帮助。祝你好运!