简体   繁体   English

在 typescript 声明中使用属性名称

[英]Using property name in typescript declaration

Is there a way to get/use the actual property name in an Typescript type definition.有没有办法在 Typescript 类型定义中获取/使用实际属性名称。

type Mapped = {
  [P:string]: P;
}

Where Mapped["foo"] is of type "foo" and Mapped["bar"] is of type "bar" , not string .其中Mapped["foo"]"foo"类型, Mapped["bar"]"bar"类型,而不是string

I tried different variations on [P:string] , [P in keyof any] , typeof P , readonly and as const or type Mapped<Props extends keyof any> = { [P in Props]: P } and everything I came up with along these lines, but P is at best typed as string , never as the actual property name.我尝试了[P:string][P in keyof any]typeof Preadonlyas consttype Mapped<Props extends keyof any> = { [P in Props]: P }以及我想出的所有变体沿着这些思路,但P最多键入为string ,而不是实际的属性名称。

What do I need this for?我需要这个做什么?

To build upon.建立在。 Typing Proxies that dynamically generate utility functions using the accessed property name.键入使用访问的属性名称动态生成实用程序函数的代理。

Something like就像是

type GetProperty = {
  [P in (keyof any)]: <T>(obj:T) => P extends keyof T ? T[P] : void;
}

My issue is, that since the generated/returned values are dynamic, I don't have a type T to keyof T the names from.我的问题是,由于生成/返回的值是动态的,所以我没有类型Tkeyof T的名称。

Could you please provide an example of expected bahaviour?您能否提供一个预期行为的例子?

var obj:Mapped = new Proxy(...);
// where the properties of `obj` should be typed as
var foo:"foo" = obj.foo;
var bar:"bar" = obj.bar;

And obj.asdf1234 should be of type "asdf1234"并且obj.asdf1234应该是"asdf1234"类型

This cannot be done in TypeScript.这不能在 TypeScript 中完成。 There is an open feature request at microsoft/TypeScript#22509 which asks for this functionality, and while you should feel free to go there and give it a or describe your use case if you think it's particularly compelling, I'd say that there's a low chance it'll happen.microsoft/TypeScript#22509有一个开放的功能请求,它要求提供此功能,虽然您应该随意到 go 并给它一个或描述您的用例,如果您认为它特别引人注目,我会说有一个发生的可能性很小。 From this comment :这个评论

It is simply not possible to model that with our current type system features (because nothing allows you to capture the literal type corresponding to the property name in a property access). model 根本不可能使用我们当前的类型系统功能(因为没有任何东西可以让您在属性访问中捕获与属性名称对应的文字类型)。

So I wouldn't hold my breath if I were you.所以如果我是你,我不会屏住呼吸。


My suggestion is to give up on dynamic property keys and instead try a single method takes the desired key as an argument:我的建议是放弃动态属性键,而是尝试一个方法,将所需的键作为参数:

const obj = {
  get<P extends PropertyKey>(p: P) {
    return <T,>(t: T): P extends keyof T ? T[P] : void =>
      (t as any)[p]

  }
}
  
const foo = {
  a: 1,
  b: "two",
  c: true
}

console.log(obj.get("a")(foo).toFixed(2)); // 1.00
console.log(obj.get("b")(foo).toUpperCase()); // TWO
obj.get("z")(foo) // void

Or, at that point, you might as well just use a function instead of a method:或者,此时,您不妨只使用 function 而不是方法:

function getter<P extends PropertyKey>(p: P) {
  return <T,>(t: T): P extends keyof T ? T[P] : void =>
    (t as any)[p]

}

console.log(getter("a")(foo).toFixed(2)); // 1.00
console.log(getter("b")(foo).toUpperCase()); // TWO
getter("z")(foo) // void

The idea is that instead of obj.a(foo) you have either obj.get("a")(foo) or just getter("a")(foo) .这个想法是,而不是obj.a(foo)你有obj.get("a")(foo)或只是getter("a")(foo) It has the same functionality but it's packaged a little differently.它具有相同的功能,但打包方式略有不同。 It might not be the exact form you want, but at least it has the advantage that TypeScript can represent what it's doing!它可能不是您想要的确切形式,但至少它具有 TypeScript 可以代表它在做什么的优势!

Playground link to code Playground 代码链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM