Mobx-state-tree: How to describe model with dynamic keys

Created on 3 Jun 2019  路  8Comments  路  Source: mobxjs/mobx-state-tree


_Question_

  • [x] I've checked documentation and searched for existing issues
  • [x] I tried the spectrum channel

Hello, I have some problems with describing the dynamic object model.

 someObject: {

  [id]: {
   collection: {...},
   meta: {...}
 },

  [id]: {
   collection: {...},
   meta: {...}
  }
...
 }

I've achieved almost the working model, but it ignore types description, and could receive any type of data. So I think, that i did something wrong.

question stale

All 8 comments

const SomeObject = types.map(types.model({
  collection: types.whatever,
  meta: types.whatever,
}))

This issue has been automatically marked as stale because it has not had recent activity in the last 10 days. It will be closed in 4 days if no further activity occurs. Thank you for your contributions.

@xaviergonz is there a way we can force the key of the map to be only certain values? maybe from an enum?

e.g.

interface PageInfo {
  title: string;
}

type Page = "home" | "about" | "contact";

const nav: Record<Page, PageInfo> = {
  about: { title: "about" },
  contact: { title: "contact" },
  home: { title: "home" },
};

Not sure, do you mean like this

enum Keys {
  A = "a",
  B = "b"
}

@model("EM")
export class EM extends Model({
  [Keys.A]: prop<string>(),
  [Keys.B]: prop<string>(),
}) {}

const em = new EM({
  [Keys.A]: "hi",
  [Keys.B]: "bye",
})

or like this

enum Keys {
  A = "a",
  B = "b"
}

const stringProp = prop<string>();

function keysAsStringProps(): {
  [k in Keys]: typeof stringProp
} {
  const props: any = {
  }
  for (const key of Object.values(Keys)) {
    props[key] = stringProp
  }
  return props
}

@model("EM")
export class EM extends Model({
  ...keysAsStringProps(),
}) {}

const em = new EM({
  [Keys.A]: "hi",
  [Keys.B]: "bye",
})

?

Or the second idea in a more generic way:

// generic function
function enumAsProps<TEnum extends string, P>(
  enm: Record<any, TEnum>,
  p: P
): {
  [k in TEnum]: P
} {
  const props: any = {}
  for (const key of Object.values(enm)) {
    props[key as PropertyKey] = p
  }
  return props
}

enum Keys {
  A = "a",
  B = "b"
}

@model("EM")
export class EM extends Model({
  ...enumAsProps(Keys, prop<string>()),
}) {}

const em = new EM({
  [Keys.A]: "hi",
  [Keys.B]: "bye",
})

Sorry, I just realized this issue was for mobx state tree instead of mobx keystone 馃槄

yeah, I meant this:

interface PageInfo {
  title: string;
}

type Page = "home" | "about" | "contact";

const nav: Record<Page, PageInfo> = {
  about: { title: "about" },
  contact: { title: "contact" },
  home: { title: "home" },
};

const NavModel = types.model({
  // is there a way that the keys of the map to be only "home" | "about" | "contact"?
  page: types.map(types.model({
    title: types.string,
  }))
})

If you use fixed keys I'd say the easiest is to just use a model instead of a map

Was this page helpful?
0 / 5 - 0 ratings