diff --git a/src/mol-plugin/state/base.ts b/src/mol-plugin/state/base.ts
index 05e2f627806696318bad63aef0b969f930260439..c3357949d08c7408b1b4bd6dbed890ac1ac682de 100644
--- a/src/mol-plugin/state/base.ts
+++ b/src/mol-plugin/state/base.ts
@@ -11,18 +11,20 @@ import { PluginBehavior } from 'mol-plugin/behavior/behavior';
 export type TypeClass = 'root' | 'data' | 'prop'
 
 export namespace PluginStateObject {
+    export type Any = StateObject<Props, any, TypeInfo>
+
     export type TypeClass = 'Root' | 'Group' | 'Data' | 'Object' | 'Representation3D' | 'Behavior'
     export interface TypeInfo { name: string, shortName: string, description: string, typeClass: TypeClass }
     export interface Props { label: string, description?: string }
 
     export const Create = StateObject.factory<TypeInfo, Props>();
 
-    export function isRepresentation3D(o?: StateObject): o is StateObject<Props, Representation.Any> {
-        return !!o && (o.type.info as TypeInfo).typeClass === 'Representation3D';
+    export function isRepresentation3D(o?: Any): o is StateObject<Props, Representation.Any, TypeInfo> {
+        return !!o && o.type.typeClass === 'Representation3D';
     }
 
-    export function isBehavior(o?: StateObject): o is StateObject<Props, PluginBehavior> {
-        return !!o && (o.type.info as TypeInfo).typeClass === 'Behavior';
+    export function isBehavior(o?: Any): o is StateObject<Props, PluginBehavior, TypeInfo> {
+        return !!o && o.type.typeClass === 'Behavior';
     }
 
     export function CreateRepresentation3D<T extends Representation.Any>(type: { name: string, shortName: string, description: string }) {
diff --git a/src/mol-plugin/ui/controls.tsx b/src/mol-plugin/ui/controls.tsx
index ec6155d9fe7225f353060490035bd4e82a64416f..71723f5b754201b6d07b7c522d86ac8613d3ed69 100644
--- a/src/mol-plugin/ui/controls.tsx
+++ b/src/mol-plugin/ui/controls.tsx
@@ -44,7 +44,7 @@ export class Controls extends React.Component<{ plugin: PluginContext }, { id: s
 
 export class _test_CreateTransform extends React.Component<{ plugin: PluginContext, nodeRef: Transform.Ref, transformer: Transformer }, { params: any }> {
     private getObj() {
-        const obj = this.props.plugin.state.data.objects.get(this.props.nodeRef)!;
+        const obj = this.props.plugin.state.data.cells.get(this.props.nodeRef)!;
         return obj;
     }
 
diff --git a/src/mol-plugin/ui/plugin.tsx b/src/mol-plugin/ui/plugin.tsx
index 111e510b9c6f261b6d43eda28d875eb6a7a0a16a..520b55069ed12fa8ca601bbf27b02e6e93a66eb0 100644
--- a/src/mol-plugin/ui/plugin.tsx
+++ b/src/mol-plugin/ui/plugin.tsx
@@ -42,7 +42,7 @@ export class _test_CurrentObject extends React.Component<{ plugin: PluginContext
     render() {
         const ref = this.props.plugin.behaviors.state.data.currentObject.value.ref;
         // const n = this.props.plugin.state.data.tree.nodes.get(ref)!;
-        const obj = this.props.plugin.state.data.objects.get(ref)!;
+        const obj = this.props.plugin.state.data.cells.get(ref)!;
 
         const type = obj && obj.obj ? obj.obj.type : void 0;
 
diff --git a/src/mol-plugin/ui/state-tree.tsx b/src/mol-plugin/ui/state-tree.tsx
index 8c7dc5dd0e36ea35a872c9586b93ad0c1a47791c..7159725571a87b72d6f93e92dacb248046d57585 100644
--- a/src/mol-plugin/ui/state-tree.tsx
+++ b/src/mol-plugin/ui/state-tree.tsx
@@ -28,20 +28,21 @@ export class StateTree extends React.Component<{ plugin: PluginContext, state: S
 export class StateTreeNode extends React.Component<{ plugin: PluginContext, nodeRef: string, state: State }, { }> {
     render() {
         const n = this.props.state.tree.nodes.get(this.props.nodeRef)!;
-        const obj = this.props.state.objects.get(this.props.nodeRef)!;
+        const cell = this.props.state.cells.get(this.props.nodeRef)!;
 
         const remove = <>[<a href='#' onClick={e => {
             e.preventDefault();
             PluginCommands.Data.RemoveObject.dispatch(this.props.plugin, { ref: this.props.nodeRef });
         }}>X</a>]</>
 
-        if (obj.status !== 'ok' || !obj.obj) {
+        if (cell.status !== 'ok' || !cell.obj) {
             return <div style={{ borderLeft: '1px solid black', paddingLeft: '7px' }}>
-                {remove} {obj.status} {obj.errorText}
+                {remove} {cell.status} {cell.errorText}
             </div>;
         }
-        const props = obj.obj!.props as PluginStateObject.Props;
-        const type = obj.obj!.type.info as PluginStateObject.TypeInfo;
+        const obj = cell.obj as PluginStateObject.Any;
+        const props = obj.props;
+        const type = obj.type;
         return <div style={{ borderLeft: '0px solid #999', paddingLeft: '0px' }}>
             {remove}[<span title={type.description}>{ type.shortName }</span>] <a href='#' onClick={e => {
                 e.preventDefault();
diff --git a/src/mol-state/object.ts b/src/mol-state/object.ts
index ed74ec0927f263fec6efe20aa313b5e464f137a6..fcd4581ec15b4986a72bfbe03917abdd855e8922 100644
--- a/src/mol-state/object.ts
+++ b/src/mol-state/object.ts
@@ -7,49 +7,45 @@
 import { UUID } from 'mol-util';
 import { Transform } from './transform';
 
-export { StateObject, StateObjectBox }
+export { StateObject, StateObjectCell }
 
-interface StateObject<P = any, D = any, Type = { }> {
+interface StateObject<P = any, D = any, T = any> {
     readonly id: UUID,
-    readonly type: StateObject.Type,
+    readonly type: StateObject.Type<T>,
     readonly props: P,
     readonly data: D
 }
 
 namespace StateObject {
-    export interface Type<Info = any> {
-        info: Info
+    export function factory<Type, CommonProps>() {
+        return <D = { }, P = {}>(type: Type) => create<P & CommonProps, D, Type>(type);
     }
 
-    export function factory<TypeInfo, CommonProps>() {
-        return <D = { }, P = {}>(typeInfo: TypeInfo) => create<P & CommonProps, D, TypeInfo>(typeInfo);
-    }
-
-    export type Ctor = { new(...args: any[]): StateObject, type: Type }
+    export type Type<I = unknown> = I
+    export type Ctor = { new(...args: any[]): StateObject, type: any }
 
-    export function create<Props, Data, TypeInfo>(typeInfo: TypeInfo) {
-        const dataType: Type<TypeInfo> = { info: typeInfo };
-        return class implements StateObject<Props, Data, Type<TypeInfo>> {
-            static type = dataType;
-            static is(obj?: StateObject): obj is StateObject<Props, Data> { return !!obj && dataType === obj.type; }
+    export function create<Props, Data, Type>(type: Type) {
+        return class implements StateObject<Props, Data, Type> {
+            static type = type;
+            static is(obj?: StateObject): obj is StateObject<Props, Data, Type> { return !!obj && type === obj.type; }
             id = UUID.create();
-            type = dataType;
+            type = type;
             constructor(public props: Props, public data: Data) { }
         }
     }
 }
 
-interface StateObjectBox {
+interface StateObjectCell {
     ref: Transform.Ref,
     props: unknown,
 
-    status: StateObjectBox.Status,
+    status: StateObjectCell.Status,
     errorText?: string,
     obj?: StateObject,
     version: string
 }
 
-namespace StateObjectBox {
+namespace StateObjectCell {
     export type Status = 'ok' | 'error' | 'pending' | 'processing'
 
     export interface Props {
diff --git a/src/mol-state/selection.ts b/src/mol-state/selection.ts
index 560a0ef4ca2c20ae6257bbeeb4107f1eb9de0ed9..e7eb61d63f257c04a176925101a334ae464f026f 100644
--- a/src/mol-state/selection.ts
+++ b/src/mol-state/selection.ts
@@ -4,14 +4,14 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-import { StateObject, StateObjectBox } from './object';
+import { StateObject, StateObjectCell } from './object';
 import { State } from './state';
 import { ImmutableTree } from './immutable-tree';
 
 namespace StateSelection {
-    export type Selector = Query | Builder | string | StateObjectBox;
-    export type NodeSeq = StateObjectBox[]
-    export type Query = (state: State) => NodeSeq;
+    export type Selector = Query | Builder | string | StateObjectCell;
+    export type CellSeq = StateObjectCell[]
+    export type Query = (state: State) => CellSeq;
 
     export function select(s: Selector, state: State) {
         return compile(s)(state);
@@ -27,8 +27,8 @@ namespace StateSelection {
         return query;
     }
 
-    function isObj(arg: any): arg is StateObjectBox {
-        return (arg as StateObjectBox).version !== void 0;
+    function isObj(arg: any): arg is StateObjectCell {
+        return (arg as StateObjectCell).version !== void 0;
     }
 
     function isBuilder(arg: any): arg is Builder {
@@ -40,13 +40,13 @@ namespace StateSelection {
     }
 
     export interface Builder {
-        flatMap(f: (n: StateObjectBox) => StateObjectBox[]): Builder;
-        mapEntity(f: (n: StateObjectBox) => StateObjectBox): Builder;
+        flatMap(f: (n: StateObjectCell) => StateObjectCell[]): Builder;
+        mapEntity(f: (n: StateObjectCell) => StateObjectCell): Builder;
         unique(): Builder;
 
         parent(): Builder;
         first(): Builder;
-        filter(p: (n: StateObjectBox) => boolean): Builder;
+        filter(p: (n: StateObjectCell) => boolean): Builder;
         subtree(): Builder;
         children(): Builder;
         ofType(t: StateObject.Type): Builder;
@@ -63,14 +63,14 @@ namespace StateSelection {
         return Object.create(BuilderPrototype, { compile: { writable: false, configurable: false, value: compile } });
     }
 
-    export function root() { return build(() => (state: State) => [state.objects.get(state.tree.rootRef)!]) }
+    export function root() { return build(() => (state: State) => [state.cells.get(state.tree.rootRef)!]) }
 
 
     export function byRef(...refs: string[]) {
         return build(() => (state: State) => {
-            const ret: StateObjectBox[] = [];
+            const ret: StateObjectCell[] = [];
             for (const ref of refs) {
-                const n = state.objects.get(ref);
+                const n = state.cells.get(ref);
                 if (!n) continue;
                 ret.push(n);
             }
@@ -78,13 +78,13 @@ namespace StateSelection {
         });
     }
 
-    export function byValue(...objects: StateObjectBox[]) { return build(() => (state: State) => objects); }
+    export function byValue(...objects: StateObjectCell[]) { return build(() => (state: State) => objects); }
 
     registerModifier('flatMap', flatMap);
-    export function flatMap(b: Selector, f: (obj: StateObjectBox, state: State) => NodeSeq) {
+    export function flatMap(b: Selector, f: (obj: StateObjectCell, state: State) => CellSeq) {
         const q = compile(b);
         return build(() => (state: State) => {
-            const ret: StateObjectBox[] = [];
+            const ret: StateObjectCell[] = [];
             for (const n of q(state)) {
                 for (const m of f(n, state)) {
                     ret.push(m);
@@ -95,10 +95,10 @@ namespace StateSelection {
     }
 
     registerModifier('mapEntity', mapEntity);
-    export function mapEntity(b: Selector, f: (n: StateObjectBox, state: State) => StateObjectBox | undefined) {
+    export function mapEntity(b: Selector, f: (n: StateObjectCell, state: State) => StateObjectCell | undefined) {
         const q = compile(b);
         return build(() => (state: State) => {
-            const ret: StateObjectBox[] = [];
+            const ret: StateObjectCell[] = [];
             for (const n of q(state)) {
                 const x = f(n, state);
                 if (x) ret.push(x);
@@ -112,7 +112,7 @@ namespace StateSelection {
         const q = compile(b);
         return build(() => (state: State) => {
             const set = new Set<string>();
-            const ret: StateObjectBox[] = [];
+            const ret: StateObjectCell[] = [];
             for (const n of q(state)) {
                 if (!set.has(n.ref)) {
                     set.add(n.ref);
@@ -133,22 +133,22 @@ namespace StateSelection {
     }
 
     registerModifier('filter', filter);
-    export function filter(b: Selector, p: (n: StateObjectBox) => boolean) { return flatMap(b, n => p(n) ? [n] : []); }
+    export function filter(b: Selector, p: (n: StateObjectCell) => boolean) { return flatMap(b, n => p(n) ? [n] : []); }
 
     registerModifier('subtree', subtree);
     export function subtree(b: Selector) {
         return flatMap(b, (n, s) => {
             const nodes = [] as string[];
             ImmutableTree.doPreOrder(s.tree, s.tree.nodes.get(n.ref), nodes, (x, _, ctx) => { ctx.push(x.ref) });
-            return nodes.map(x => s.objects.get(x)!);
+            return nodes.map(x => s.cells.get(x)!);
         });
     }
 
     registerModifier('children', children);
     export function children(b: Selector) {
         return flatMap(b, (n, s) => {
-            const nodes: StateObjectBox[] = [];
-            s.tree.nodes.get(n.ref)!.children.forEach(c => nodes.push(s.objects.get(c!)!));
+            const nodes: StateObjectCell[] = [];
+            s.tree.nodes.get(n.ref)!.children.forEach(c => nodes.push(s.cells.get(c!)!));
             return nodes;
         });
     }
@@ -160,17 +160,17 @@ namespace StateSelection {
     export function ancestorOfType(b: Selector, t: StateObject.Type) { return unique(mapEntity(b, (n, s) => findAncestorOfType(s, n.ref, t))); }
 
     registerModifier('parent', parent);
-    export function parent(b: Selector) { return unique(mapEntity(b, (n, s) => s.objects.get(s.tree.nodes.get(n.ref)!.parent))); }
+    export function parent(b: Selector) { return unique(mapEntity(b, (n, s) => s.cells.get(s.tree.nodes.get(n.ref)!.parent))); }
 
-    function findAncestorOfType({ tree, objects }: State, root: string, type: StateObject.Type): StateObjectBox | undefined {
+    function findAncestorOfType({ tree, cells }: State, root: string, type: StateObject.Type): StateObjectCell | undefined {
         let current = tree.nodes.get(root)!;
         while (true) {
             current = tree.nodes.get(current.parent)!;
             if (current.ref === tree.rootRef) {
-                return objects.get(tree.rootRef);
+                return cells.get(tree.rootRef);
             }
-            const obj = objects.get(current.ref)!.obj!;
-            if (obj.type === type) return objects.get(current.ref);
+            const obj = cells.get(current.ref)!.obj!;
+            if (obj.type === type) return cells.get(current.ref);
         }
     }
 }
diff --git a/src/mol-state/state.ts b/src/mol-state/state.ts
index aecbbcb655199e861f70702faaf3750677bdaef7..5851edbd99380b66604ee36b49ac837c6704db1f 100644
--- a/src/mol-state/state.ts
+++ b/src/mol-state/state.ts
@@ -4,7 +4,7 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-import { StateObject, StateObjectBox } from './object';
+import { StateObject, StateObjectCell } from './object';
 import { StateTree } from './tree';
 import { Transform } from './transform';
 import { ImmutableTree } from './immutable-tree';
@@ -23,16 +23,16 @@ class State {
     get tree() { return this._tree; }
     get current() { return this._current; }
 
-    readonly objects: State.Objects = new Map();
+    readonly cells: State.Cells = new Map();
     readonly context: StateContext;
 
     getSnapshot(): State.Snapshot {
         const props = Object.create(null);
-        const keys = this.objects.keys();
+        const keys = this.cells.keys();
         while (true) {
             const key = keys.next();
             if (key.done) break;
-            const o = this.objects.get(key.value)!;
+            const o = this.cells.get(key.value)!;
             props[key.value] = { ...o.props };
         }
         return {
@@ -68,7 +68,7 @@ class State {
                     taskCtx,
                     oldTree,
                     tree: tree,
-                    objects: this.objects,
+                    objects: this.cells,
                     transformCache: this.transformCache
                 };
                 // TODO: have "cancelled" error? Or would this be handled automatically?
@@ -84,7 +84,7 @@ class State {
         const root = tree.getValue(tree.rootRef)!;
         const defaultObjectProps = (params && params.defaultObjectProps) || { }
 
-        this.objects.set(tree.rootRef, {
+        this.cells.set(tree.rootRef, {
             ref: tree.rootRef,
             obj: rootObject,
             status: 'ok',
@@ -101,7 +101,7 @@ class State {
 }
 
 namespace State {
-    export type Objects = Map<Transform.Ref, StateObjectBox>
+    export type Cells = Map<Transform.Ref, StateObjectCell>
 
     export interface Snapshot {
         readonly tree: StateTree.Serialized,
@@ -120,7 +120,7 @@ namespace State {
         taskCtx: RuntimeContext,
         oldTree: StateTree,
         tree: StateTree,
-        objects: State.Objects,
+        objects: State.Cells,
         transformCache: Map<Ref, unknown>
     }
 
@@ -142,7 +142,7 @@ namespace State {
         }
     }
 
-    function findUpdateRoots(objects: State.Objects, tree: StateTree) {
+    function findUpdateRoots(objects: State.Cells, tree: StateTree) {
         const findState = {
             roots: [] as Ref[],
             objects
@@ -177,7 +177,7 @@ namespace State {
         return deletes;
     }
 
-    function setObjectState(ctx: UpdateContext, ref: Ref, status: StateObjectBox.Status, errorText?: string) {
+    function setObjectState(ctx: UpdateContext, ref: Ref, status: StateObjectCell.Status, errorText?: string) {
         let changed = false;
         if (ctx.objects.has(ref)) {
             const obj = ctx.objects.get(ref)!;
@@ -185,7 +185,7 @@ namespace State {
             obj.status = status;
             obj.errorText = errorText;
         } else {
-            const obj: StateObjectBox = { ref, status, version: UUID.create(), errorText, props: { ...ctx.stateCtx.defaultObjectProps } };
+            const obj: StateObjectCell = { ref, status, version: UUID.create(), errorText, props: { ...ctx.stateCtx.defaultObjectProps } };
             ctx.objects.set(ref, obj);
             changed = true;
         }
@@ -219,7 +219,7 @@ namespace State {
         }
     }
 
-    function findAncestor(tree: StateTree, objects: State.Objects, root: Ref, types: { type: StateObject.Type }[]): StateObject {
+    function findAncestor(tree: StateTree, objects: State.Cells, root: Ref, types: { type: StateObject.Type }[]): StateObject {
         let current = tree.nodes.get(root)!;
         while (true) {
             current = tree.nodes.get(current.parent)!;
diff --git a/src/perf-tests/state.ts b/src/perf-tests/state.ts
index dbe511f90b081a196d0c1fb2f4a729560bcbe8d0..799c28dc6ea3a2a02c5902783b872f49993ba51c 100644
--- a/src/perf-tests/state.ts
+++ b/src/perf-tests/state.ts
@@ -68,7 +68,7 @@ function hookEvents(state: State) {
     state.context.events.object.created.subscribe(e => console.log('created:', e.ref));
     state.context.events.object.removed.subscribe(e => console.log('removed:', e.ref));
     state.context.events.object.replaced.subscribe(e => console.log('replaced:', e.ref));
-    state.context.events.object.stateChanged.subscribe(e => console.log('stateChanged:', e.ref, state.objects.get(e.ref)!.status));
+    state.context.events.object.stateChanged.subscribe(e => console.log('stateChanged:', e.ref, state.cells.get(e.ref)!.status));
     state.context.events.object.updated.subscribe(e => console.log('updated:', e.ref));
 }
 
@@ -91,7 +91,7 @@ export async function testState() {
 
     await state.update(tree1).run();
     console.log('----------------');
-    console.log(util.inspect(state.objects, true, 3, true));
+    console.log(util.inspect(state.cells, true, 3, true));
 
     console.log('----------------');
     const jsonString = JSON.stringify(StateTree.toJSON(tree2), null, 2);
@@ -103,7 +103,7 @@ export async function testState() {
 
     console.log('----------------');
     await state.update(treeFromJson).run();
-    console.log(util.inspect(state.objects, true, 3, true));
+    console.log(util.inspect(state.cells, true, 3, true));
 
     console.log('----------------');