{"id":27551871,"url":"https://github.com/traits-ts/core","last_synced_at":"2025-04-19T09:58:31.679Z","repository":{"id":273134766,"uuid":"918800775","full_name":"traits-ts/core","owner":"traits-ts","description":"Traits for TypeScript Classes (Core)","archived":false,"fork":false,"pushed_at":"2025-04-06T11:46:14.000Z","size":588,"stargazers_count":24,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-15T21:55:50.432Z","etag":null,"topics":["class","core","mixin","oop","trait","typescript"],"latest_commit_sha":null,"homepage":"https://traits-ts.org","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/traits-ts.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-01-18T22:11:49.000Z","updated_at":"2025-04-06T11:46:16.000Z","dependencies_parsed_at":"2025-01-18T23:19:24.842Z","dependency_job_id":"95894db0-5be1-42f2-8d81-c9583326e8c1","html_url":"https://github.com/traits-ts/core","commit_stats":null,"previous_names":["rse/traits","traits-ts/core"],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/traits-ts%2Fcore","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/traits-ts%2Fcore/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/traits-ts%2Fcore/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/traits-ts%2Fcore/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/traits-ts","download_url":"https://codeload.github.com/traits-ts/core/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249669904,"owners_count":21308668,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["class","core","mixin","oop","trait","typescript"],"created_at":"2025-04-19T09:58:31.052Z","updated_at":"2025-04-19T09:58:31.672Z","avatar_url":"https://github.com/traits-ts.png","language":"TypeScript","readme":"\n\u003cimg src=\"https://raw.githubusercontent.com/traits-ts/core/refs/heads/master/etc/logo.svg\" width=\"200\" style=\"float: right\" align=\"right\" alt=\"\"/\u003e\n\n@traits-ts/core\n===============\n\n**Traits for TypeScript Classes (Core)**\n\n\u003cp/\u003e\n\u003ca href=\"https://traits-ts.org\"\u003eProject Home\u003c/a\u003e |\n\u003ca href=\"https://github.com/traits-ts/core\"\u003eGithub Repository\u003c/a\u003e |\n\u003ca href=\"https://npmjs.com/@traits-ts/core\"\u003eNPM Distribution\u003c/a\u003e\n\n\u003cp/\u003e\n\u003cimg src=\"https://nodei.co/npm/@traits-ts/core.png?downloads=true\u0026stars=true\" alt=\"\"/\u003e\n\n[![github (author stars)](https://img.shields.io/github/stars/rse?logo=github\u0026label=author%20stars\u0026color=%233377aa)](https://github.com/rse)\n[![github (author followers)](https://img.shields.io/github/followers/rse?label=author%20followers\u0026logo=github\u0026color=%234477aa)](https://github.com/rse)\n\u003cbr/\u003e\n[![npm (project release)](https://img.shields.io/npm/v/@traits-ts/core?logo=npm\u0026label=npm%20release\u0026color=%23cc3333)](https://npmjs.com/@traits-ts/core)\n[![npm (project downloads)](https://img.shields.io/npm/dm/@traits-ts/core?logo=npm\u0026label=npm%20downloads\u0026color=%23cc3333)](https://npmjs.com/@traits-ts/core)\n\nAbout\n-----\n\nThis is a TypeScript library providing a *trait* (aka *mixin*)\nfacility for extending classes with *multiple* base functionalities,\nalthough TypeScript/JavaScript technically do not allow multiple\ninheritance.\n\nFor this, it internally leverages the regular `class extends` mechanism\nand \"linearizes\" the trait hierarchy at the JavaScript level, so it\nis does not have to manipulate the run-time objects at all. At the\nTypeScript level, it is fully type-safe and recursively derives all\nproperties of the traits a class is derived from.\n\nThis library consists of just three API functions: `trait` for defining\na trait (or sub-trait), the API function `derive` for deriving a base\nclass from one or more defined traits, and the API type-guard function\n`derived` to ensure an object has the functionality of a trait under\nrun-time.\n\nSee also [@traits-ts/stdlib](https://github.com/traits-ts/stdlib) for\na companion library of standard, reusable, generic, typed traits (aka mixins),\nbased on this base library. Currently, this standard library consists\nof the reusable traits *Identifiable*, *Configurable*, *Bindable*,\n*Subscribable*, *Hookable*, *Finalizable*, *Traceable*, and\n*Serializable*.\n\nInstallation\n------------\n\n```sh\n$ npm install --save @traits-ts/core\n```\n\nAPI\n---\n\nThe Application Programming Interface (API) of **@traits-ts/core** consists\nof just three API functions and can be used in the following way:\n\n```ts\n//  Import API functions.\nimport { trait, derive, derived } from \"@traits-ts/core\"\n//       =====  ======  =======\n\n//  Define regular trait Foo.\nconst Foo = trait((base) =\u003e class Foo extends base { ... })\n//          =====================     ============\n\n//  Define regular sub-trait Foo, inheriting from super-traits Bar and Qux.\nconst Foo = trait([ Bar, Qux ], (base) =\u003e class Foo extends base { ... })\n//                ============\n\n//  Define generic trait Foo.\nconst Foo = \u003cT\u003e() =\u003e trait((base) =\u003e class Foo extends base { ... \u003cT\u003e ... })\n//          =====                                                 ===\n\n//  Define generic sub-trait Foo, inheriting from super-traits Bar and Qux.\nconst Foo = \u003cT\u003e() =\u003e trait([ Bar, Qux\u003cT\u003e ], (base) =\u003e class Foo extends base { ... \u003cT\u003e ... })\n//          =====          ===============                                         ===\n\n//  Define application class with features derived from traits Foo, Bar and Qux.\nclass Sample extends derive(Foo, Bar\u003cBaz\u003e, Qux) { ... }\n//                   ==========================\n\n//  Define application class with features derived from traits and a trailing regular class\nclass Sample extends derive(Foo, Bar\u003cBaz\u003e, Qux, EventEmitter) { ... }\n//                                              ============\n\n//  Call super constructor from application class constructor.\nclass Sample extends derive(...) { constructor () { super(); ... } ... }\n//                                                  =======\n\n//  Call super method from application class method.\nclass Sample extends derive(...) { foo () { ...; super.foo(...); ... } ... }\n//                                               ==============\n\n//  Check whether application class is derived from a trait.\nconst sample = new Sample(); if (derived(sample, Foo)) ...\n//                               ====================\n```\n\nExamples\n-------\n\n### Regular, Orthogonal/Independent Traits\n\n```ts\nimport { trait, derive } from \"@traits-ts/core\"\n\nconst Duck = trait((base) =\u003e class extends base {\n    squeak () { return \"squeak\" }\n})\nconst Parrot = trait((base) =\u003e class extends base {\n    talk () { return \"talk\" }\n})\nconst Animal = class Animal extends derive(Duck, Parrot) {\n    walk () { return \"walk\" }\n}\n\nconst animal = new Animal()\n\nanimal.squeak() // -\u003e \"squeak\"\nanimal.talk()   // -\u003e \"talk\"\nanimal.walk()   // -\u003e \"walk\"\n```\n\n### Regular, Bounded/Dependent Traits\n\n```ts\nimport { trait, derive } from \"@traits-ts/core\"\n\nconst Queue = trait((base) =\u003e class extends base {\n    private buf: Array\u003cnumber\u003e = []\n    get () { return this.buf.pop() }\n    put (x: number) { this.buf.unshift(x) }\n})\nconst Doubling = trait([ Queue ], (base) =\u003e class extends base {\n    put (x: number) { super.put(2 * x) }\n})\nconst Incrementing = trait([ Queue ], (base) =\u003e class extends base {\n    put (x: number) { super.put(x + 1) }\n})\nconst Filtering = trait([ Queue ], (base) =\u003e class extends base {\n    put (x: number) { if (x \u003e= 0) super.put(x) }\n})\n\nconst MyQueue = class MyQueue extends\n    derive(Filtering, Doubling, Incrementing, Queue) {}\n\nconst queue = new MyQueue()\n\nqueue.get()    // -\u003e undefined\nqueue.put(-1)\nqueue.get()    // -\u003e undefined\nqueue.put(1)\nqueue.get()    // -\u003e 3\nqueue.put(10)\nqueue.get()    // -\u003e 21\n```\n\n### Generic, Bounded/Dependent Traits\n\n```ts\nimport { trait, derive } from \"@traits-ts/core\"\n\nconst Queue = \u003cT\u003e() =\u003e trait((base) =\u003e class extends base {\n    private buf: Array\u003cT\u003e = []\n    get ()     { return this.buf.pop() }\n    put (x: T) { this.buf.unshift(x) }\n})\nconst Tracing = \u003cT\u003e() =\u003e trait([ Queue\u003cT\u003e ], (base) =\u003e class extends base {\n    private trace (ev: string, x?: T) { console.log(ev, x) }\n    get ()     { const x = super.get(); this.trace(\"get\", x); return x }\n    put (x: T) { this.trace(\"put\", x); super.put(x) }\n})\n\nconst MyTracingQueue = class MyTracingQueue extends\n    derive(Tracing\u003cstring\u003e, Queue\u003cstring\u003e) {}\n\nconst queue = new MyTracingQueue()\n\nqueue.put(\"foo\")  // -\u003e console: put foo\nqueue.get()       // -\u003e console: get foo\nqueue.put(\"bar\")  // -\u003e console: put bar\nqueue.put(\"qux\")  // -\u003e console: put qux\nqueue.get()       // -\u003e console: get bar\nqueue.get()       // -\u003e console: get qux\n```\n\nHistory\n-------\n\nThe **@traits-ts/core** library was developed in January 2025 by Dr. Ralf\nS. Engelschall. It is heavily inspired by Scala traits and the API\nof **@ddd-ts/traits**, although **@traits-ts/core** is a \"from scratch\"\nimplementation for TypeScript.\n\nSupport\n-------\n\nThe work on this Open Source Software was financially supported by the\ngerman non-profit organisation *SEA Software Engineering Academy gGmbH*.\n\nLicense\n-------\n\nCopyright \u0026copy; 2025 Dr. Ralf S. Engelschall (http://engelschall.com/)\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be included\nin all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftraits-ts%2Fcore","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftraits-ts%2Fcore","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftraits-ts%2Fcore/lists"}