如何使用魔术TypeScript或递归?

时间:2018-07-01 00:16:16

标签: typescript typescript2.0

我有两种方法:

public prop<K extends keyof ResponseInvitation.RootObject>(key: K) {
    return this._has(key) ? this.user[key] : null;
  }

  private _has(prop: string): boolean {
    return this.user.hasOwnProperty(prop);
  }

我这样使用:

let prop = this.prop('profile'); // Return object 

在返回的属性为对象的情况下,热调用this.prop的链:

 let prop = this.prop(this.prop('profile').organization);

上面的注释表示我试图通过名称profile获取属性。它返回其中具有属性organization作为字符串的对象。

我认为我需要这个:

private _has(prop: string): boolean {
    let prop = this.user.hasOwnProperty(prop);

    if (typeof prop == 'object') {
       return this._has(prop);
    }
}

关于我的问题,我试图重写逻辑并获得以下工作代码:

interface RootObject { 
  name: string;
  organization: Org; 
}

interface Org { 
  name: string;
}

class A { 

  public user: any;
  public last: string;

public prop<K extends keyof RootObject>(key: K) {
  let  prop = this._has(key) ? this.user[key] : null;

  if (key == this.last) { 
    return prop;
  }

  if (typeof prop == 'object') {
    let k = Object.keys(prop)[0] as K;
    this.user = prop;
    return this.prop(k);
  }

  }

  private _has(prop: string): boolean {
    return this.user.hasOwnProperty(prop);
  }

  public propString(properties: string) { 
    this.last = properties.split('.').slice(-1).pop();
  }

}

let b = {
  'organization': {
    'name': 'Oleg'
  }
};

let a = new A();
a.user = b;
a.propString('organization.name');
let d = a.prop('organization');
console.log(d);

1 个答案:

答案 0 :(得分:3)

由于您遗漏了许多类实现,因此我不确定您要查找的内容。我将为您要实现的目标提供更一般的解决方案:

type WrapIfObject<T> = T extends object ? ObjectWrapper<T> : T; 
class ObjectWrapper<T> {
  constructor(public object: T) { }
  prop<K extends keyof T>(k: K): WrapIfObject<T[K]>;
  prop<K extends keyof T>(k: K): T[K] | ObjectWrapper<T[K]> {
    const val = this.object[k];
    return (typeof val === "object") ? new ObjectWrapper(val) : val;
  }
}

上面是一个名为ObjectWrapper的类,该类包装了您在构造函数中传递的对象。当您使用对象的键之一调用prop()方法时,如果返回值不是对象,则返回值将是属性值,或者将{适当的价值。通过这种方式,您可以将调用链接到ObjectWrapper,直到获得非对象值为止。请注意,prop()prop()的返回类型是conditional type而不是并集,这使编译器能够以更易于使用的方式强烈键入输出。

让我们看看它是如何工作的:

WrapIfObject<T[K]>

上面的类型检查没有错误; TypeScript知道const val = {a: {b: "hey"}, c: "you"}; const valWrap = new ObjectWrapper(val); console.log(valWrap.prop("a").prop("b").charAt(0)); // "h" console.log(valWrap.prop("c").charAt(0)); // "y" valWrap.prop("a").prop("b"),而stringvalWrap.prop("c")。如果您做错了事,它将抱怨:

string

由于条件类型的distributive属性,它将在正确的位置产生并集:

const oops = valWrap.prop("a").charAt(0); // error!
// Property 'charAt' does not exist on type 'ObjectWrapper<{ b: string; }>'.

注意如何知道const x = new ObjectWrapper({a: Math.random() < 0.5 ? "string" : {b: 3}}); const y = x.prop("a") ; // string | ObjectWrapper<{b: number}> const z = (typeof y === "string") ? y.length : y.prop("b"); // number console.log(z); // 6 or 3 一个y 还是一个string

无论如何,希望您可以使用它来给您一个解决问题的想法。祝你好运!