{"id":111,"date":"2020-11-15T20:44:09","date_gmt":"2020-11-15T19:44:09","guid":{"rendered":"https:\/\/info.edython.eu\/?p=111"},"modified":"2020-11-16T09:48:01","modified_gmt":"2020-11-16T08:48:01","slug":"using-generics-to-decorate-a-class","status":"publish","type":"post","link":"https:\/\/info.edython.eu\/index.php\/2020\/11\/15\/using-generics-to-decorate-a-class\/","title":{"rendered":"Using generics to decorate a class"},"content":{"rendered":"\n<p>We previously explained how to <a href=\"https:\/\/info.edython.eu\/index.php\/2020\/11\/15\/using-generics-to-decorate-a-class\/(ouvre un nouvel onglet)\">add new attributes to a class using a decorator<\/a> and properly use the decorated class accordingly to the type system. Here we use a property which type is a generic and a method which argument is a generic.<\/p>\n\n\n\n<h2>Add a property<\/h2>\n\n\n\n<p>Here we add a property named <code>data<\/code> which is an instance of some <code>Data<\/code> class.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"typescript\" class=\"language-typescript\">class Data {\n    name: string = ''\n}\ninterface IFoo&lt;D extends Data> {\n  data?: D\n}\nfunction decorate&lt;\n  T extends { new (...args: any[]): {} },\n  D extends Data\n>(constructor: T) {\n  return class extends constructor implements IFoo&lt;D> {\n    data?: D\n  }\n}\n@decorate\nclass Foo {\n  static new&lt;D extends Data>() {\n    return new Foo() as TFoo&lt;D>\n  }\n}\ntype TFoo&lt;D extends Data> = Foo &amp; IFoo&lt;D><\/code><\/pre>\n\n\n\n<p>Here is how one can use it<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"typescript\" class=\"language-typescript\">var foo = Foo.new()\nconsole.log(foo.data)\nfoo.data = {\n  name: 'blabla'\n}\nconsole.log(foo.data.name)<\/code><\/pre>\n\n\n\n<p>We can also decorate using a strict subclass of data<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"typescript\" class=\"language-typescript\">class XData extends Data {\n    x = true\n}\n@decorate\nclass Bar {\n  static new&lt;D extends XData>() {\n    return new Bar() as TBar&lt;D>\n  }\n}\ntype TBar&lt;D extends XData> = Bar &amp; IFoo&lt;D><\/code><\/pre>\n\n\n\n<p>Here is how one can use it<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"typescript\" class=\"language-typescript\">var bar = Bar.new()\nbar.data = {\n  name: 'blabla',\n  x: true\n}\nconsole.log(bar.data.name)<\/code><\/pre>\n\n\n\n<p>If we want <code>Foo<\/code> to also accept <code>Data<\/code> subclasses, we must add any string signature to <code>Data<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"typescript\" class=\"language-typescript\">class Data {\n    [$: string]: any\n    name: string = ''\n}<\/code><\/pre>\n\n\n\n<p>Here is how one can use it<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"typescript\" class=\"language-typescript\">foo.data = {\n  name: 'blabla',\n  x: true\n}\nconsole.log(foo.data.name)<\/code><\/pre>\n\n\n\n<h2>Add a method<\/h2>\n\n\n\n<p>Here we add a method named <code>test<\/code> which sole argument is an instance of some <code>Data<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"typescript\" class=\"language-typescript\">class Data {\n    [$: string]: any\n    name: string = 'foo'\n}\ninterface IFoo&lt;D extends Data> {\n  test(data: D): void\n}\nfunction decorate&lt;\n  T extends { new (...args: any[]): {} },\n  D extends Data\n>(constructor: T) {\n  class U extends constructor implements IFoo&lt;D> {\n    test(data: D) {\n      return data.name\n    }\n  }\n  return U\n}\n@decorate\nclass Foo {\n  static new&lt;D extends Data>() {\n    return new Foo() as TFoo&lt;D>\n  }\n}\ntype TFoo&lt;D extends Data> = Foo &amp; IFoo&lt;D><\/code><\/pre>\n\n\n\n<p>Here is how we can use it<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"typescript\" class=\"language-typescript\">var foo = Foo.new()\nconsole.log(foo.test(new Data()))<\/code><\/pre>\n\n\n\n<p>Subclassing the <code>Data<\/code> class<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"typescript\" class=\"language-typescript\">class XData extends Data {\n    x = 421\n}\n@decorate\nclass Bar {\n  static new&lt;D extends XData>() {\n    return new Bar() as TBar&lt;D>\n  }\n  constructor(name: string) {\n    super()\n    this.name = name\n  }\n}\ntype TBar&lt;D extends XData> = Bar &amp; IFoo&lt;D><\/code><\/pre>\n\n\n\n<p>and some usage<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"typescript\" class=\"language-typescript\">var bar = Bar.new()\nconsole.log(bar.test(new XData('bar')))\n\nconsole.log(foo.test(new XData('baz')))<\/code><\/pre>\n\n\n\n<h2>Playgrounds<\/h2>\n\n\n\n<p><a href=\"https:\/\/www.typescriptlang.org\/play?jsx=0&amp;module=0&amp;ts=4.0.5#code\/MYGwhgzhAEAiYBczQN4ChqegbQCQC5oIEAnASwDsBzAXULAoE8MsKwBbAU0OPOugC80AOTC0AXzSUEnEgDMwwTtACSAMQD2GgDyxonAB4yKAExjwkAPlQsTiMAH5CsCWjkBXCsARkNFaCacwBokiJzaLAAq+kacpjAo0BScAO7QABQAdNlgJFQQ9EzYNACUhCji0OIANCx6hsZmcPZolunBFLzu3iGEkSU2mKCQMACqMY0wHV09JNBk7AAOIJxcFAgw6lq61uhYAfZOcCySmCScCO4k-qOuAAKBwaEyaMNQ0Joag0RIPsBJqV0EziTQsYDaAz2WHOl2uALSn3SA0g0Einx2J1cCEYi2UaO29Vi8WaVkEHy00AAZKp0bBLGg0AA3XLQOQUoSfTLJFJI15+CAaFaZEAaKjpNkaTJ2JAlNxaKX2MlQthcQjCABG4E1YDEkmmgs4wtF4vl0rAXI4nFlr3A7wAGmDgcTHVDMAYyaR3Jx7o8QmEbSNoAAhFlQ4iIMj-blAhogmAO+wQ75nC5Xfzc4O5JHQFGREMkDGYSSSbG41H5mNEpoJ0lCfNUmkE+lMlnqll13Jc1K86YIA5IJUsFXcETa7XCWpuwie72SNskBUDoRmvmdA1GsUa3IT6Dzxfm4fWiX7skr-VCkWbiU749mi1cWVAA\">Typescript playground<\/a> to add a property.<br><a href=\"https:\/\/www.typescriptlang.org\/play?jsx=0&amp;module=0&amp;ts=4.0.5#code\/MYGwhgzhAEAiYBczQN4ChqegbQCQC5oIEAnASwDsBzAXULAoE8MsKwBbAU0OPOugC80AOQAzAPbjhaAL5pKCTiVFhgnaAEkAYpIA8saJwAeiigBMY8JAD5ULRcQAUZxGEKwAlIQBu4smdk0UQBXCmAEMnEKaDNOYHESRE5dFgAVQxNOcxgUaApOAHdoRwA6MrASKgh6JmwaL1QZaBkAGhYDY1MLOFc0a0d4il5g8ITCVI87TFBIGABVDK6YQeHRkmgydgAHEE4uCgQYbT1YW3QsaAcEZ1d3SfOL6BJOBGCSaJckErYuFkw5f4sZ6vd7QOaBAACsXiiUUaBmUGgOnEUyISAiwDyhX0iyy3SsYH69z+Txeb2i+SKyMck0g0FSyP01hYcjkCEYW3UDJOuOyPRsgiRkmgADJNIzTmg0N4KtAJCihMjvoUafCohBxLsSiBxFRHPKSldHJT+WAaR4PFKETAABoE3n41yo6bq0gjBAJY0cbhovhUYmPIjBTkkVWBhAACzIEG+3sFP04JNZaChcQSSXh4ERACFZQ9iIgyJjKTjOnjbQSic7SSCKYVoLnQ7SYKlG0yWYF2Zz6W2Opk+XbXLYhI3ReKTszpbKAEaykcVZUFVUrTWcbW6xyzkiGzhOE2DpCOYRb4QWy1qoar9d6g1G-cEo+zgBep4taCAA\">Typescript playground<\/a> to add a method.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>We previously explained how to add new attributes to a class using a decorator and properly use the decorated class accordingly to the type system. Here we use a property which type is a generic and a method which argument is a generic. Add a property Here we add a property named data which is &hellip; <a href=\"https:\/\/info.edython.eu\/index.php\/2020\/11\/15\/using-generics-to-decorate-a-class\/\" class=\"more-link\">Continuer la lecture<span class=\"screen-reader-text\"> de &laquo;&nbsp;Using generics to decorate a class&nbsp;&raquo;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[5],"tags":[],"_links":{"self":[{"href":"https:\/\/info.edython.eu\/index.php\/wp-json\/wp\/v2\/posts\/111"}],"collection":[{"href":"https:\/\/info.edython.eu\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/info.edython.eu\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/info.edython.eu\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/info.edython.eu\/index.php\/wp-json\/wp\/v2\/comments?post=111"}],"version-history":[{"count":6,"href":"https:\/\/info.edython.eu\/index.php\/wp-json\/wp\/v2\/posts\/111\/revisions"}],"predecessor-version":[{"id":123,"href":"https:\/\/info.edython.eu\/index.php\/wp-json\/wp\/v2\/posts\/111\/revisions\/123"}],"wp:attachment":[{"href":"https:\/\/info.edython.eu\/index.php\/wp-json\/wp\/v2\/media?parent=111"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/info.edython.eu\/index.php\/wp-json\/wp\/v2\/categories?post=111"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/info.edython.eu\/index.php\/wp-json\/wp\/v2\/tags?post=111"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}