{"id":22400951,"url":"https://github.com/samdenty/mix-classes","last_synced_at":"2025-07-31T15:31:31.219Z","repository":{"id":57298552,"uuid":"184895883","full_name":"samdenty/mix-classes","owner":"samdenty","description":"Seamlessly combine class inheritance with composition, guaranteed to work with any class","archived":false,"fork":false,"pushed_at":"2019-10-21T22:26:50.000Z","size":837,"stargazers_count":7,"open_issues_count":5,"forks_count":0,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-11-26T21:15:11.391Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","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/samdenty.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}},"created_at":"2019-05-04T13:05:00.000Z","updated_at":"2020-12-08T08:42:43.000Z","dependencies_parsed_at":"2022-08-26T18:02:27.516Z","dependency_job_id":null,"html_url":"https://github.com/samdenty/mix-classes","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samdenty%2Fmix-classes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samdenty%2Fmix-classes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samdenty%2Fmix-classes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samdenty%2Fmix-classes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/samdenty","download_url":"https://codeload.github.com/samdenty/mix-classes/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228258291,"owners_count":17892657,"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":[],"created_at":"2024-12-05T08:17:31.989Z","updated_at":"2024-12-05T08:17:32.957Z","avatar_url":"https://github.com/samdenty.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mix-classes\n\nEasily add typescript-safe mixins to JS classes, with support for generics, constructors, overloading and more. Correctly handles `this` for each class, so it'll work with anything.\n\n- Typescript generics\n- Pass arguments to mixins, by providing an array of arguments\n- Supports `super` calls in overloaded methods\n- Use [`instanceof`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/instanceof) to check for mixin classes\n- Handles the `this` inside classes, so that they always access their local scope first. No need to worry about name-collisions\n\n```ts\nimport { Mix } from 'mix-classes'\n\nclass Contactable {\n  constructor(public email: string, public phone?: string) {}\n}\nclass Nameable {\n  constructor(public name: string) {}\n}\nclass Website {\n  constructor(public websiteUrl: string) {}\n}\n\nclass Developer extends Mix(Nameable, Contactable, Website) {\n  constructor() {\n    super(['Bob'], ['hi@example.com'], ['https://example.com'])\n  }\n}\n\nclass Company extends Mix(Nameable, Contactable) {\n  constructor() {\n    super(['Apple'], ['hi@apple.com', '18-00'], ['https://apple.com'])\n  }\n}\n\nconst developer = new Developer()\ndeveloper.name\ndeveloper.email\ndeveloper.websiteUrl\n\nconst company = new Company()\ncompany.name\ncompany.email\ncompany.phone\ncompany.websiteUrl\n```\n\n## Constructor arguments\n\nYou can pass custom constructor arguments to each mixin within an array inside the `super` call. The arguments order is dependant on the `mix` array order.\n\n```ts\nimport { Mix } from 'mix-classes'\n\nclass Nameable {\n  constructor(public name: string) {}\n}\n\nclass Ageable {\n  constructor(public age: number) {}\n}\n\nclass Person extends Mix(Nameable, Ageable) {\n  constructor() {\n    super(['Bob'], [50])\n    //     ^ name argument for Nameable\n    //              ^ age argument for Ageable\n  }\n}\n```\n\n## Overloading\n\nAll mixins are seperate classes with different `this` values, meaning you don't need to worry about name collisions.\n\n```ts\nimport { Mix, getMixin } from 'mix-classes'\n\nclass A {\n  variable = 'a'\n  public a() {\n    return this.variable\n  }\n}\n\nclass B {\n  variable = 'b'\n  public b() {\n    return this.variable\n  }\n}\n\nclass Test extends Mix(A, B) {\n  constructor() {\n    super()\n\n    // The default value is the last mixin specified\n    console.log(this.variable) // 'b'\n\n    // Use getMixin to get overloaded properties\n    console.log(getMixin(this, A).variable) // 'a'\n\n    // Mixins retain access to their local variables\n    this.a() // 'a'\n    this.b() // 'b'\n  }\n}\n\nconst test = new Test()\n```\n\n## Typescript generics\n\nTypescript generics are supported, but it requires using Typescript's declaration merging.\n\nTo use them, simply wrap the class that you want to pass generics to in `Generic()`, and then add an interface with the same name as the class you want it in.\n\nBefore:\n\n```ts\nimport { Mix } from 'mix-classes'\n\nclass MyClass\u003cT extends string = 'initial'\u003e extends Mix(\n  User,\n  Nameable,\n  Ageable\n) {}\n```\n\nAfter:\n\n```ts\nimport { Generic, Mix } from 'mix-classes'\n\n// Move all generic type signatures to the interface\n// including default values.\ninterface MyClass\u003cT extends string = 'initial'\u003e extends User\u003c'bob'\u003e {}\n\nclass MyClass\u003cT\u003e extends Mix(Generic(User), Nameable, Ageable) {}\n```\n\n```ts\nimport { Mix, Generic } from 'mix-classes'\n\nclass B {}\n\nclass Role\u003cType extends string\u003e {\n  constructor(public type: Type) {}\n}\n\nclass User\u003cUsername extends string\u003e {\n  constructor(public username: Username) {}\n}\n\ninterface Admin extends User\u003c'bob'\u003e, Role\u003c'admin'\u003e {}\n\nclass Admin extends Mix(Generic(User), Generic(Role), B) {\n  constructor() {\n    super(['bob'], ['admin'])\n  }\n}\n\nconst test = new Admin()\ntest.username // type 'bob'\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsamdenty%2Fmix-classes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsamdenty%2Fmix-classes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsamdenty%2Fmix-classes/lists"}