Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Simplify Records #174

Closed
Closed
@eteeselink

Description

@eteeselink

Hi Lee (& contributors), as I wrote on Hacker News, I'd like to discuss some ideas about Records with you. I'm looking for your opinion most of all, at this point. If there is consensus, I'd be happy to help implementing things as well.

I use Records a lot in my codebases - usually I have Map<string, SomeRecordClass>, possibly nested in another map or two, all over the place.

I like the concept of generating a Record class at runtime. It doesn't mesh well with TypeScript, but it's very powerful and really leverages some of the things JavaScript can do better than many other languages.

What I'm not so sure about, is the very large set of methods a Record has. I don't often iterate over all the keys in a Record. I don't usually want to build a map of all fields in a record except those that are more than 5. Maybe, somehow, it's not very useful that Record derives from Map. I'm not even sure it needs to implement Iterable.

As long as you can convert it into something that does.

So, how about this:

  • Record does not implement Map or anything like that
  • Record has only two methods, set and toMap.
  • The rest of a Record's namespace is nicely saved for fields. It means you can easily access fields called anything other than 'set' and 'toMap'. You'd need to do record.toMap().get('set') if your Record has a field called 'set'. Feels controversial, but really in practice this seems like an edge case.
  • Note that you don't really need update: You can just do var newRecord = oldRecord.set('someSet', oldRecord.someSet.add(5)); which is hardly more verbose, and even shorter when you don't have TypeScript / ES6 lambda syntax.

This approach has a number of advantages. First of all, it becomes feasible to simply implement it with a vanilla JS object and Object.freeze. I'm not sure what the performance characteristics are, but I suspect that the structures underlying Map (and thus, the current Record) aren't that much more efficient than a simple shallow clone for very small amounts of fields (like is typical for records). set would just shallow-clone the object, overwrite one value (or more, maybe), then freeze the new object.

That, in turn has a number of tangible advantages:

  • First, shorthand field access (record.fieldName) works on ES3 too (currently it is implemented with defineProperty so only ES5 browsers and up will manage)
  • Second, I suspect that there's more chances for leveraging TypeScript - Immutable.Record could simply be a base class (with set and toMap implementations) that people can derive their own classes from. I haven't completely worked this out yet, but I feel like there's ways here to at least make it somewhat better from the TypeScript perspective.

Finally, somewhat offtopic, but why did you choose obj.set('field', value) over obj.set({field: value})?

I know that all this totally breaks backward compatibility. At this stage I'm more interested in discussing the concept, and then if more people think it's a good idea, we can see if/how to implement it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions