扩展 Typescript 类属性方法

问题描述 投票:0回答:1

我想构建如下所示的东西。我尝试找了很多地方,但都没有得到我想要的。

// Typescript Class or interface
export class(or interface) Person {
firstName: string;
lastName: string;
}

现在在 Angular 组件中,我想使用这样的东西:

//Assume Person type is class
let p = new Persons();

然后,当我编写 p.firstName.toPropertyName() 返回属性名称时,我想实现类似的目标。 “名” 这里 toPropertyName() 是我对对象的任何属性的扩展方法。

再次,我知道我可以使用那些 object.keys 并实现上述行为,但这并不适合我的场景。

在 c# 中,使用反射可以很容易地实现这一点,但在 typescript/javascript 中很难做到这一点。

javascript angular typescript javascript-objects typescript-typings
1个回答
0
投票

问题是 JavaScript 中并没有像

nameof
这样的东西。不过,也有解决方法,请参阅Javascript 中的字符串形式的变量名称了解更多信息。


我尝试提出一种generic类型安全的方法,它不会自动将类属性映射到字符串,而是强制您通过类型检查返回正确的字符串。这有一个很大的优点:

toPropertyName()
返回属性名称的字符串文字类型。像
Object.keys({ someVariable })[0]
这样的东西只会给你一个任意的
string

另一方面,它的代码太多,对于现实世界的情况来说不太实用。我使用

get
ters 来修改属性的返回值。

type PropertyGetValue<V, T, K extends keyof T> = {
  value: V;
  toPropertyName: () => K;
};

class Extension<T> {
  protected getPropertyGetValue<V, K extends keyof T>(
    value: V,
    propertyKey: K,
  ): PropertyGetValue<V, T, K> {
    return { value, toPropertyName: () => propertyKey };
  }
}

class Person extends Extension<Person> {
  private _firstname: string;
  private _lastname: string;

  constructor(firstname: string, lastname: string) {
    super();

    this._firstname = firstname;
    this._lastname = lastname;
  }

  get firstname(): PropertyGetValue<
    typeof this._firstname,
    Person,
    "firstname"
  > {
    return super.getPropertyGetValue(this._firstname, "firstname");
  }

  set firstname(value: string) {
    this._firstname = value;
  }

  get lastname(): PropertyGetValue<typeof this._firstname, Person, "lastname"> {
    return super.getPropertyGetValue(this._lastname, "lastname");
  }

  set lastname(value: string) {
    this._firstname = value;
  }
}

const p = new Person("Jason", "Becker");

const firstname = p.firstname.value;
//    ^? const firstname: string
const firstnamePropertyName = p.firstname.toPropertyName();
//    ^? const firstnamePropertyName: "firstname"

TypeScript 游乐场

© www.soinside.com 2019 - 2024. All rights reserved.