Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

copyable

Package Overview
Dependencies
Maintainers
1
Versions
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

copyable

Immutable data objects for TypeScript (and JavaScript)

  • 1.0.0
  • latest
  • Source
  • npm
  • Socket score

Version published
Maintainers
1
Created
Source

logo

Original image

Immutable data objects with type safe .copy(), .map() and .equals() inspired by case class in Scala and data class in Kotlin

Installation

yarn add copyable

TypeScript >= 2.8 required.

Usage

import { Copyable } from 'copyable';

class Person extends Copyable {
  constructor(readonly name: string, readonly age: number) {
    super();
  }
}

const person1 = new Person('John', 25);

const person2 = person1.copy({ name: 'James', age: 20 });
// -> Person(name="James", age=20)
person1.copy('age', 30);
// -> Person(name="John", age=30)

person1.map({
  name: name => 'Older ' + name,
  age: age => age + 20
});
// -> Person(name="Older John", age=45)
person1.map('age', age => age + 20);
// -> Person(name="John", age=45)

person1.equals(person2); // false
person1.equals(new Persion('John', 25)); // true

person1.toString();
/* -> 
  Person(
    name="John",
    age=25
  )
*/

Type safety

person1.copy({ age: '20' }); // comple error: Types of property 'age' are incompatible. Type 'string' is not assignable to type 'number'.

person1.copy({ notAPropertyOfPerson: 20 }); // comple error: Object literal may only specify known properties

person1.copy({ equals: () => false }); // Nope. Can't replace methods.

API Reference

copy

  • copy(patch?: Patch<this>): this

    Returns a copy of the object.

    Accepts an object that contains new values for specified properties

    import { Copyable } from 'copyable';
    
    class Person extends Copyable {
      constructor(readonly name: string, readonly age: number) {
        super();
      }
    }
    
    const person1 = new Person('John', 25);
    person1.copy({ name: 'James', age: 20 });
    // -> Person(name="James", age=20)
    
    Parameters
    • (Optional) patch: Patch<this>
    Returns

    typeof this

  • copy<K extends PatchKey<this>>(key: K, val: this[K]): this

    Returns a copy of the object.

    Accepts a key and a new value for it

    import { Copyable } from 'copyable';
    
    class Book extends Copyable {
      constructor(readonly title: string) {
        super();
      }
    }
    
    const book1 = new Book('TypeScript Deep Dive');
    book1.copy('title', 'TypeScript handbook');
    // -> Book(title="TypeScript handbook")
    
    Parameters
    • key: K extends PatchKey<this>
    • value: this[key]
    Returns

    typeof this

map

  • map(patchMap: MapPatch<this>): this

    Maps the object. Allows to copy the object based on its current values.

    Accept an object that contains mapper for specified properties.

    const person1 = new Person('John', 25);
    // John got older
    person1.map({
      name: name => 'Older ' + name,
      age: age => age + 20
    });
    // -> Person(name="Older John", age=45)
    
    Parameters
    • (Optional) patchMap: MapPatch<this>
    Returns

    typeof this

  • map<K extends PatchKey<this>>(key: K, mapper: Mapper<this[K]>): this

    Maps the object. Allows to copy the object based on its current values.

    Accept a key and a mapper for it.

    import { Copyable } from 'copyable';
    
    class Book extends Copyable {
      constructor(readonly title: string) {
        super();
      }
    }
    
    const book1 = new Book('TypeScript Deep Dive');
    book1.map('title', title => title + ' Part 2');
    // -> Book(title="TypeScript Deep Dive Part 2")
    
Parameters
  • key: K extends PatchKey<this>
  • mapper: Mapper<this[K]>
Returns

typeof this

equals

equals(other: this | null | undefined): boolean

Checks for structural equality

Note that the comparision is shallow!

const book1 = new Book('TypeScript Deep Dive');
const book2 = new Book('TypeScript handbook');

book1.equals(book2); // false
book1.equals(new Book('TypeScript Deep Dive')); // true
Returns

boolean

toString

toString(): string

Returns a string representation of the object that is a bit nicer than the default one ('[object Object]')

const person = new Person('John', 25);
person.toString();
// Person(
//   name="John",
//   age=25
// )
Returns

string

Can I use it with JavaScript?

Yes! You won't have any type checking, of course, so you risk shooting yourself in a foot.

Prior art

Inspired by Case Classes in Scala and Data Classes in Kotlin.

Implementation influenced by ts-copyable and dataclass.

FAQs

Package last updated on 16 Feb 2019

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc