typescript 装饰器 decorator

Decorators are just a clean syntax for wrapping a piece of code with a function

The Journey Begins With Class Decorators

class Families {
  private houses = ["Lannister", "Targaryen"];

  get() {
    return this.houses;
  }
  post(request) {
    this.houses.push(request.body);
  }
}

class Castles {
  private castles = ["Winterfell", "Casterly Rock"];

  get() {
    return this.castles;
  }
  post(request) {
    this.castles.push(request.body);
  }
}

  

const httpEndpoints = {};

function registerEndpoint(constructor) {
  const className = constructor.name;
  const endpointPath = "/" + className.toLowerCase();
  httpEndpoints[endpointPath] = new constructor();
}

registerEndpoint(Families)
registerEndpoint(Castles)

console.log(httpEndpoints) // {"/families": Families, "/castles": Castles}
httpEndpoints["/families"].get() // ["Lannister", "Targaryen"]

  

const httpEndpoints = {};

function registerEndpoint(constructor) {
  const className = constructor.name;
  const endpointPath = "/" + className.toLowerCase();
  httpEndpoints[endpointPath] = new constructor();
}

@registerEndpoint
class Families {
  // implementation...
}

@registerEndpoint
class Castles {
  // implementation...
}

console.log(httpEndpoints) // {"/families": Families, "/castles": Castles}
httpEndpoints["/families"].get() // ["Lannister", "Targaryen"]

  

Unleash the Power of the Method Decorator

const protectedMethods = [];

function protect(target, propertyKey, descriptor) {
  const className = target.constructor.name;
  protectedMethods.push(className + "." + propertyKey);
}

@registerEndpoint
class Families {
  private houses = ["Lannister", "Targaryen"];

  @protect
  get() {
    return this.houses;
  }
  
  @protect
  post(request) {
    this.houses.push(request.body);
  }
}

console.log(protectedMethods) // ["Families.get", "Families.post"]

  

function nope(target, propertyKey, descriptor) {
  descriptor.value = function() {
    console.log("nope");
  };
  return descriptor;
}

@registerEndpoint
class Families {
  private houses = ["Lannister", "Targaryen"];

  @nope
  get() {
    return this.houses;
  }
}

httpEndpoints["/families"].get() // nope

  

function protect(target, propertyKey, descriptor) {
  const originalFunction = descriptor.value;

  descriptor.value = function(request) {
    if (request.token !== "123") {
      throw new Error("forbiden!");
    }
    const bindedOriginalFunction = originalFunction.bind(this)
    const result = bindedOriginalFunction(request)
    return result
  };

  return descriptor;
}

@registerEndpoint
class Families {
  private houses = ["Lannister", "Targaryen"];

  @protect
  get() {
    return this.houses;
  }
}

httpEndpoints["/families"].get({token: "123"}) // ["Lannister", "Targaryen"]
httpEndpoints["/families"].get({}) // Uncaught Error: forbiden!

  

Gain More Power With Decorator Factories

const httpEndpoints = {};

function registerEndpoint(constructor) {
  const className = constructor.name;
  const endpointPath = "/" + className.toLowerCase();
  httpEndpoints[endpointPath] = new constructor();
}

@registerEndpoint
class Families {
  // implementation...
}

@registerEndpoint
class Castles {
  // implementation...
}

console.log(httpEndpoints) // {"/families": Families, "/castles": Castles}
httpEndpoints["/families"].get() // ["Lannister", "Targaryen"]

  

const httpEndpoints = {};

function registerEndpointFactory(endpointPath) {
  return function registerEndpoint(constructor) {
    httpEndpoints[endpointPath] = new constructor();
  }
}

@registerEndpointFactory("/families/stark/members")
class StarkMembers {
  private members = ["Robb", "Sansa", "Arya"];

  get() {
    return this.members;
  }

  @protect
  post(request) {
    this.members.push(request.body);
  }
}

console.log(httpEndpoints) // {"/families/stark/members": StarkMembers}
httpEndpoints["/families/stark/members"].get() // ["Robb", "Sansa", "Arya"]

  

function protect(token) {
  return function(target, propertyKey, descriptor) {
    const originalFunction = descriptor.value;

    descriptor.value = function(request) {
      if (request.token !== token) {
        throw new Error("forbiden!");
      }
      const bindedOriginalFunction = originalFunction.bind(this);
      const result = bindedOriginalFunction(request);
      return result;
    };

    return descriptor;
  };
}

class StarkMembers {
  private members = ["Robb", "Sansa", "Arya"];

  @protect("abc")
  post(request) {
    this.members.push(request.body);
  }
}

  

Conclusion

 

yay, you did it!

原文地址:https://www.cnblogs.com/oxspirt/p/13729609.html