diff --git a/src/Ecs/Data.ts b/src/Ecs/Data.ts
index 2443ba4..eadc634 100644
--- a/src/Ecs/Data.ts
+++ b/src/Ecs/Data.ts
@@ -19,10 +19,22 @@ export type Store<T> = (T & HasGeneration)[];
 export type SparseStore<T> = Record<number, T & HasGeneration>;
 export class Data {
     entity: Store<EntityState> = [];
-
-    [name: string]: Store<{}> | SparseStore<{}>;
 }
 
+// Ergonomic Lookup typings
+type StoreKeysOf<DATA> = {
+    [K in keyof DATA]: DATA[K] extends Record<number, infer T & HasGeneration> ? K : never;
+};
+type StoreKeys<DATA extends Data> = StoreKeysOf<DATA>[keyof DATA];
+type ItemType<S> = S extends Record<number, infer T & HasGeneration> ? T : never;
+type StoreType<DATA extends Data, K> = K extends keyof DATA ? ItemType<DATA[K]> : never;
+type StoreTypes<DATA extends Data, K> = {
+    [I in keyof K]: StoreType<DATA, K[I]>;
+};
+type MaybeStoreTypes<DATA extends Data, K> = {
+    [I in keyof K]: StoreType<DATA, K[I]> | null;
+};
+
 /**
  * Create an entity in the store
  * @param data store
@@ -31,7 +43,7 @@ export class Data {
  * @returns the new entity's ID and generation
  */
 type Assigner<DATA extends Data> = {
-    [S in keyof DATA]?: Pick<DATA[S][number], Exclude<keyof DATA[S][number], "generation">>
+    [S in StoreKeys<DATA>]?: StoreType<DATA, S>
 };
 export function Create<DATA extends Data>(data: DATA, assign: Assigner<DATA>, state = Liveness.ALIVE): Id {
     const entities = data.entity;
@@ -57,7 +69,8 @@ export function Create<DATA extends Data>(data: DATA, assign: Assigner<DATA>, st
     };
 
     for(const key in assign) {
-        data[key][freeId] = {...(assign[key] as {}), generation};
+        const store = data[key as keyof Data] as Store<{}>|SparseStore<{}>;
+        store[freeId] = {...(assign as Record<string, HasGeneration>)[key] as {}, generation};
     }
 
     return [freeId, generation];
@@ -76,16 +89,6 @@ export function Remove<DATA extends Data>(data: DATA, [id, generation]: Id, stat
     }
 }
 
-// Ergonomic Lookup typings
-type ItemType<S> = S extends Record<number, infer T> ? T : never;
-type StoreType<DATA extends Data, K> = K extends keyof DATA ? ItemType<DATA[K]> : never;
-type StoreTypes<DATA extends Data, K extends (keyof DATA)[]> = {
-    [I in keyof K]: StoreType<DATA, K[I]>;
-};
-type MaybeStoreTypes<DATA extends Data, K extends (keyof DATA)[]> = {
-    [I in keyof K]: StoreType<DATA, K[I]> | null;
-};
-
 /**
  * Look up components that may or may not exist for an entity
  * @param data store
@@ -93,12 +96,13 @@ type MaybeStoreTypes<DATA extends Data, K extends (keyof DATA)[]> = {
  * @param components names of components to look for
  * @returns the cooresponding components, with unfound ones replaced by nulls
  */
-export function Lookup<DATA extends Data, K extends (keyof DATA)[]>(data: DATA, [id, generation]: Id, ...components: K): MaybeStoreTypes<DATA, K> {
+export function Lookup<DATA extends Data, K extends StoreKeys<DATA>[]>(data: DATA, [id, generation]: Id, ...components: K): MaybeStoreTypes<DATA, K> {
     const entity = data.entity[id];
     // inactive entities are fine to lookup, but dead ones are not
     if(entity && entity.generation == generation && entity.alive != Liveness.DEAD) {
         return components.map(storeName => {
-            const component = data[storeName][id];
+            const store = data[storeName] as unknown as Store<{}>|SparseStore<{}>;
+            const component = store[id];
             if(component && component.generation == generation) {
                 return component;
             } else {
@@ -113,32 +117,32 @@ export function Lookup<DATA extends Data, K extends (keyof DATA)[]>(data: DATA,
 // Ergonomic Join typings
 export function Join<
     DATA extends Data,
-    A extends keyof DATA,
+    A extends StoreKeys<DATA>,
 > (
     data: DATA,
     a: A,
 ): [
     Id,
-    DATA[A][number]
+    StoreType<DATA, A> & {}
 ][];
 export function Join<
     DATA extends Data,
-    A extends keyof DATA,
-    B extends keyof DATA,
+    A extends StoreKeys<DATA>,
+    B extends StoreKeys<DATA>,
 > (
     data: DATA,
     a: A,
     b: B,
 ): [
     Id,
-    DATA[A][number],
-    DATA[B][number]
+    StoreType<DATA, A> & {},
+    StoreType<DATA, B> & {},
 ][];
 export function Join<
     DATA extends Data,
-    A extends keyof DATA,
-    B extends keyof DATA,
-    C extends keyof DATA,
+    A extends StoreKeys<DATA>,
+    B extends StoreKeys<DATA>,
+    C extends StoreKeys<DATA>,
 > (
     data: DATA,
     a: A,
@@ -146,16 +150,16 @@ export function Join<
     c: C,
 ): [
     Id,
-    DATA[A][number],
-    DATA[B][number],
-    DATA[C][number]
+    StoreType<DATA, A> & {},
+    StoreType<DATA, B> & {},
+    StoreType<DATA, C> & {},
 ][];
 export function Join<
     DATA extends Data,
-    A extends keyof DATA,
-    B extends keyof DATA,
-    C extends keyof DATA,
-    D extends keyof DATA,
+    A extends StoreKeys<DATA>,
+    B extends StoreKeys<DATA>,
+    C extends StoreKeys<DATA>,
+    D extends StoreKeys<DATA>,
 > (
     data: DATA,
     a: A,
@@ -164,18 +168,18 @@ export function Join<
     d: D,
 ): [
     Id,
-    DATA[A][number],
-    DATA[B][number],
-    DATA[C][number],
-    DATA[D][number]
+    StoreType<DATA, A> & {},
+    StoreType<DATA, B> & {},
+    StoreType<DATA, C> & {},
+    StoreType<DATA, D> & {},
 ][];
 /**
  * Query a Data collection for all Alive entities possessing the named set of Components.
  * @returns an array of tuples containing the matching entity [ID, generation]s & associated Components
  */
-export function Join<DATA extends Data, K extends keyof DATA>(data: DATA, ...components: K[]): [Id, ...{}[]][] {
+export function Join<DATA extends Data, K extends StoreKeys<DATA>[]>(data: DATA, ...components: K): [Id, ...{}[]][] {
     const entities = data.entity;
-    const stores: (Store<{}>|SparseStore<{}>)[] = components.map(name => data[name]);
+    const stores = components.map(name => data[name] as unknown as (Store<{}>|SparseStore<{}>));
 
     const results: [Id, ...{}[]][] = [];
     const firstStore = stores[0];