Git Product home page Git Product logo

immutableassign's People

Contributors

ca-pli avatar dependabot[bot] avatar engineforce avatar greenkeeper[bot] avatar liukun avatar noahm avatar shroo-paulli avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

immutableassign's Issues

Unexpected behavior when Proxy === undefined

Great job with the library.
Type-safe alternative to immutable.js was exactly what my team was looking for.

We found iassign to behave consistently until we ran our web app through a compatibility test with ie11.
In ie11, and I suspect other environments that do not natively support Proxy class, we get a peculiar behavior when we try to assign a new key-value pair to our target object.

Input Code

const actual = iassign(
 {},
 t => t.KEY,
 () => 'VALUE'
)

Expected Behavior

actual === { KEY: 'VALUE' }

Actual Behavior

actual === 'VALUE'

Bug Report

I played around with the codebase and found the internal getPropPaths returning different outcomes between environments that support the Proxy class and ones that do not.

getPropPaths(t => t.key, {}) === ['key'] // when Proxy exists
getPropPaths(t => t.key, {}) === []      // when Proxy === undefined

This seems to cause the above Input Code to behave as expected within Proxy supported environments and fail in environments, such as ie11, that do not support the class.

I understand that we can get the expected behavior with overload 2, which may be the intended usage, but I believe the inconsistent behavior is something that can be addressed.

Error when using bracket notation to access property in getProp

I get an error if I use the bracket notation in the getProp function. The property names in my application are dynamic so I pass all the information used to construct them through the external context parameter. However, this results in a Cannot find quoted text for undefined error. The below code reproduces this problem:

var myState = {
  questions: {
    page_51: [
      { id: 100, text: 'Question One' },
      { id: 101, text: 'Question Two' }
    ],
    page_53: [
      { id: 500, text: 'Question Three' },
      { id: 502, text: 'Question Four' }
    ]
  }
};

const insertAction = {
  pageId: 53,
  position: 1,
  question: { id: 505, text: 'The new question' },
};

var newState = iassign(
    myState,
    (s, context) => s.questions[`page_${context.pageId}`],
    (questions) => {
      questions.splice(insertAction.position, 0, insertAction.question);
      return questions;
    },
    { pageId: insertAction.pageId }
);

console.log(newState);

Nicer API

Hi, thanks for the amazing helper.

When using this library in conjunction with lodash/fp, I found that the API would be much more powerful if the argument order was changed (iteratee first, data last), and if it was curried, in the spirit of lodash-fp.

I usually define a function called mutate this way:

const mutate = (getter,setter,context?) => (state) => iassign(state,getter,setter,context,{freeze:true})

The resulting function mutate is extremely helpful, as it allows to represent "mutations" in a declarative way. These mutations can then be applied to data. Here is an example of use:

const reducer = (state = initialState, action) => {

    switch (action.type) {

    case "TICK":
        return mutate(
          state=>state.time,
          time=>time+1
        )(state)
        
        ...

How to use from typescript

I am trying to use immutable-assign like this from typescript:

import iassign = require('immutable-assign');

But I get this errors:

ERROR in [at-loader] node_modules\immutable-assign\src\iassign.ts:50:16 
    Cannot find name 'module'.

ERROR in [at-loader] node_modules\immutable-assign\src\iassign.ts:50:46 
    Cannot find name 'module'.

ERROR in [at-loader] node_modules\immutable-assign\src\iassign.ts:51:25 
    Cannot find name 'require'.

ERROR in [at-loader] node_modules\immutable-assign\src\iassign.ts:51:34 
    Cannot find name 'exports'.

ERROR in [at-loader] node_modules\immutable-assign\src\iassign.ts:51:65 
    Cannot find name 'module'.

ERROR in [at-loader] node_modules\immutable-assign\src\iassign.ts:71:25 
    Cannot find namespace 'DeepFreeze'.

ES6 arrow functions without the `return` keyword don't work as getProp

The library currently requires the keyword return inside the getProp function.

This is not compatible with one-liner ES6 arrow functions without curly braces, such as a => a+5, you have to write a => { return a+5 }, which is not a huge issue, but not ideal.

It works when the code is transpiled into ES5, but people will eventually stop doing that in the future. It is already unnecessary for node.js projects.

Not sure what the performance hit of detecting such syntax would be though 😐 .

An in-range update of coveralls is breaking the build 🚨

The devDependency coveralls was updated from 3.0.3 to 3.0.4.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

coveralls is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ❌ continuous-integration/travis-ci/push: The Travis CI build failed (Details).
  • βœ… coverage/coveralls: First build on greenkeeper/coveralls-3.0.4 at 85.971% (Details).

Commits

The new version differs by 5 commits.

  • 8ac4325 version bump
  • 9d9c227 Bump extend from 3.0.1 to 3.0.2 (#226)
  • 33119a7 Bump js-yaml from 3.11.0 to 3.13.1 (#225)
  • f5549c7 Bump handlebars from 4.1.0 to 4.1.2 (#224)
  • 4df732b Style fix (#211)

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Cannot assign freeze property

Trying to write: iassign.freeze = true in vscode results in this error:
[ts] Cannot assign to 'freeze' because it is a constant or a read-only property.

This is because es6 imports are constants by default, so their properties are readonly.

How to handle possibly null values in getProp?

I'm using strictNullChecks in my project. It seems that the getProp function does not allow if-statements in the function body. There for I'm getting Error: getProp() function has statements other than 'return' errors.

Is there a way to workaround this?

Here's an example which produces this error:

  import i from "immutable-assign";

  interface IState {
      foo?: {
          bar?: number;
      };
  }

  const state: IState = {};

  // Does not compile
  //     foo.tsx (12,32): Object is possibly 'undefined'. (2532)
  // const newState = i(state, s => s.foo.bar, () => 1);

  // Throws at runtime with 
  //     Error: getProp() function has statements other than 'return': const foo = s.foo;
  const newState = i(
      state,
      s => {
          const foo = s.foo;
          if (foo) {
              return foo.bar;
          }

          return null;
      },
      () => 1,
  );

Error when freeze and ignoreIfNoChange both true

Should it be possible to set both freeze and ignoreIfNoChange to true?

When I run the following code using version 1.0.34:

var iassign = require("immutable-assign");

iassign.freeze = true;
iassign.ignoreIfNoChange = true;

var map1 = { a:1, b:2, c:3 };

// 1: Calling iassign() to update map1.b, using overload 2
var map2 = iassign(
    map1,
    function (m) { m.b = 50; return m; }
);

I get this error:

.../node_modules/immutable-assign/deploy/iassign.js:75
                newValue = setProp(obj);
                           ^
TypeError: Cannot assign to read only property 'b' of object '#<Object>'

Support classes

Hi, great library, I love the idea of not having to use any special structures to achieve immutable updates.

Would it be possible to also support ES6 classes when updating the object? Right now, if I have

class Hello {
    constructor(world) { this.world = world }
    say() { console.log(this.world) }
}
const a = new Hello("World")

and I update a, the resulting object no longer has the same __proto__, so I can't call say on it, etc.

Module "immutable-assign" has no default export.

I am using ImmutableAssign along with TypeScript on a project and import it using this:

import iassign from "immutable-assign"

However, the above gives me this linting error: error TS1192: Module '"immutable-assign"' has no default export. Is this something that you can fix?

Add a function to only freeze (if enabled)

When using seamless-immutable, I usually do Immutable.from(result) for all my AJAX-calls, so I am sure it will not be changed further down the line.

It would be nice to have a similar function for ImmutableAssign, that would Object.Freeze if enabled, otherwise it would do nothing.

Example:

const immutableResult = iassign(result)

Feature request: Allow specifying the path of property to update by an array

Hi, great library ! I use it a lot !

Unfortunately I came across a problem I could not figure how to solve.

I have a hierarchical structure representing a collapsible nested list items. The type is:

export interface NavNode {
    readonly title: string,
    readonly icon?: string,
    readonly opened?: boolean,
    readonly children?: NavTree
}

export interface NavTree {
    readonly [url: string]: NavNode
}

And it looks like:

{
	"/computer-sciences/": {
		title: "Computer sciences",
		opened: false,
		children: {
		    "artificial-intelligence/": {
		        title: "Artificial intelligence",
		        opened: false,
		        children: {
		            "machine-learning/": {
		                title: "Machine learning",
		                opened: false,
		                children: {
		                    "introduction/": {
		                        title: "Introduction"
		                    },
		                    "common-models/": {
		                        title: "Common Models"
		                    },
		                    "common-training-methods/": {
		                        title: "Common training methods"
		                    },
		                    "ensemble-techniques/": {
		                        title: "Ensemble techniques"
		                    },
		                }
		            }
		        }
		    }
		}
	}
}

My problem arises when I try to handle a click on an internal non-leaf node. I can't write getProp as, for example:

navTree => navTree["/computer-sciences/"]["children"]["artificial-intelligence/"]["opened"]

Because I don't know the path until a node is clicked and the information on the node is an array describing it's path, like:

["/computer-sciences/", "artificial-intelligence/"]

It would be nice if there was a feature of iassign allowing an array for the path of the property to update. In the previous case, the array would be:

["/computer-sciences/", "children", "artificial-intelligence/", "opened"]

And the usage may look like:

iassign(
   obj,
   ["/computer-sciences/", "children", "artificial-intelligence/", "opened"],
   opened => !opened)

iassign does not work correctly with ES6 Map

Hi, thanks for this great helper library.

Does this library support ES6 Map? For me the following example does not work correctly. 'm' is always empty in the setProp and therefore map3 (or mapX) contains always one element after adding further elements.

import * as iassign from 'immutable-assign';

iassign.setOption({useConstructor: true});

let map1 = new Map();

  let map2 = iassign(
    map1,
    m => {
      m.set(0, 'first'); return m;
    }
  );

  let map3 = iassign(
    map2,
    m => { m.set(1, 'second'); return m; }
  );

  console.log(map1.size) // size: 0
  console.log(map2.size) // size: 1
  console.log(map3.size) // size: 1

Additionally, I have to set the useConstructor Option in every file (after import), that the option is applied correctly.

Unexpected behaviour when console.log-ing or using lodash/fp/find

I was getting very inconsistent results using lodash's lodash/fp/find to locate the element that I'd like to replace. So after some testing, we reduce to the following ... situation.

I get the distinct impression that this may not be fixable?

const nested1 = { a:{ b:{ c:[ {id: 3}, {id: 4}, {id: 5}], d: 1 } } };

    const nested2 = iassign(
      nested1,
      function (n) {
        console.log("BOOM")
        const f = n.a.b.c[1]
        console.log(f)
        console.log(f == n.a.b.c[1])
        return f
      },
      function (c1) { return { id: 12}; }
    );

    console.log(JSON.stringify(nested2, null, 2))

gives output:

      BOOM
      { id: 4 }
      true
      BOOM
      { id: 4 }
      false
      {
        "a": {
          "b": {
            "c": [
              {
                "id": 3
              },
              {
                "id": 4
              },
              {
                "id": 5
              }
            ],
            "d": 1
          }
        }
      }

Why is the getter function being executed twice?

Proxy polyfill not applied on iOS 9.0 / Android 6.0

I'm developing mobile app with React-Native + TypeScript. After upgrading iassign to 2.0.0, JS engine throws Can't find variable: Proxy error.

Environment

ImmutableAssign - 2.0.0
React Native - 0.48.2
OS: iOS 9.0 / Android 6.0 ( iOS 10.0+ works fine )

Provide initialization method

It would be nice to have a better way to initialize immutable object than:

const obj = iassign({
  prop: 'value'
}, (obj) => (obj))

Maybe make the setter function optional, and just initialize frozen object if it's not provided?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.