如何使用代理定义属性

时间:2017-12-23 19:50:22

标签: javascript typescript

我有一个带有代理的类,它看起来像这样:

export class Row<T extends ModelItems> {

  private _row: T = <T>{}

  public constructor(rowItems?: T) {
    if (rowItems) { this._row = rowItems }
    return new Proxy(this, {
      get: function (target, prop) {
        return (<any>target)[prop] || target._row[prop] || ''
      }
      /* set(): snipped */
  }
}

当我这样做时:

interface User {
    id: number
    first: string
    last: string
    username: string
}

let row = new Row<User>({/* My object */})

如何获取它,以便在我键入row时,我会获得User界面中定义的项目列表。现在所有建议的都是对象根目录中的实际方法/属性。

我试过这个:

export interface Row<T extends ModelItems> {
  [key: string]: T 
}

除了告诉我我的方法没有被定义属性之外,这似乎没什么帮助

1 个答案:

答案 0 :(得分:2)

您希望Row<T>的实例本身也是T;是对的吗? TypeScript不会让你做class Row<T> implements T这样的事情,也不会轻易推断出它自己。相反,你可以做类似以下的事情:

export class _Row<T> {
 // ... your definition above
}
// Row type alias
export type Row<T extends ModelItems> = _Row<T> & T;
// Row value alias
export const Row = _Row as {
  new <T>(rowItems?: T): Row<T>
  prototype: _Row<{}>
}

这在运行时的行为大致相同,但现在TypeScript会理解Row<T>的实例具有T具有的所有属性:

declare const u: User;
let row = new Row(u); // inferred as Row<User>
row.username // string

如果您尝试表示不同的内容,例如Row<T>的行为类似于T的所有键但具有可能空字符串属性的内容,则可以替换// Row type alias用这个代替:

// Row type alias
export type Row<T extends ModelItems> = _Row<T> &
  {[K in keyof T]: T[K] | ''};

并验证它是否符合您的预期:

declare const u: User;
let row = new Row(u); // inferred as Row<User>
row.id // number || ''

希望有所帮助;祝你好运!