# Source: https://mikro-orm.io/docs/metadata-providers.md

# Metadata Providers

As part of entity discovery process, MikroORM uses so called `MetadataProvider` to get necessary type information about our entities' properties.

> We can also implement custom metadata provider by extending abstract `MetadataProvider` class.

There are 3 built-in metadata providers we can use:

## TsMorphMetadataProvider[​](#tsmorphmetadataprovider "Direct link to TsMorphMetadataProvider")

With `TsMorphMetadataProvider` MikroORM will use [`ts-morph`](https://github.com/dsherret/ts-morph) to read TypeScript source files of all entities to be able to detect all types. Thanks to this, defining the type is enough for runtime validation.

To use it, first install the `@mikro-orm/reflection` package.

```
import { TsMorphMetadataProvider } from '@mikro-orm/reflection';

await MikroORM.init({
  metadataProvider: TsMorphMetadataProvider,
  // ...
});
```

If we use folder-based discovery, we should specify paths to the compiled entities via `entities` as well as paths to the TS source files of those entities via `entitiesTs`. When we run the ORM via `ts-node`, the latter will be used automatically, or if we explicitly pass `preferTs: true` in the config. Note that `preferTs: true` should not be part of production config.

> When running via `node`, `.d.ts` files are used to obtain the type, so we need to ship them in the production build. TS source files are no longer needed (since v4). Be sure to enable `compilerOptions.declaration` in our `tsconfig.json`.

After the discovery process ends, all [metadata will be cached](https://mikro-orm.io/docs/metadata-cache.md). By default, `FileCacheAdapter` will be used to store the cache inside `./temp` folder in JSON files.

> We can generate production cache via CLI command `mikro-orm cache:generate`.

> We can implement custom cache adapter by implementing `CacheAdapter` interface.

## ReflectMetadataProvider[​](#reflectmetadataprovider "Direct link to ReflectMetadataProvider")

`ReflectMetadataProvider` uses `reflect-metadata` module to read the type from decorator metadata exported by TypeScript compiler.

We will need to install `reflect-metadata` module and import at the top of our app's bootstrap script (e.g. `main.ts` or `app.ts`).

```
import 'reflect-metadata';
```

Next step is to enable `emitDecoratorMetadata` flag in our `tsconfig.json`.

> As this approach does not have performance impact, metadata caching is not really necessary.

```
await MikroORM.init({
  metadataProvider: ReflectMetadataProvider,
  // ...
});
```

### Limitations and requirements[​](#limitations-and-requirements "Direct link to Limitations and requirements")

While `TsMorphMetadataProvider` do not suffer from any of the following problems, it brings a performance penalty (that can be limited only to cases where you change your entity definition via metadata caching) and is in general not compatible with other compilers like webpack or babel. It also requires you to deploy `.d.ts` files alongside your compiled `.js` entities (more about this in the [deployment section](https://mikro-orm.io/docs/deployment.md)).

#### Explicit types[​](#explicit-types "Direct link to Explicit types")

> Since v6, the type is inferred automatically based on the runtime default value, as long as it is possible to instantiate the entity without passing any constructor arguments. As long as you keep your constructors aware of that, this limitation does not apply.

Type inference is not supported, we need to always explicitly specify the type:

```
@Property()
createdAt: Date = new Date();
```

#### Collection properties and Identified references[​](#collection-properties-and-identified-references "Direct link to Collection properties and Identified references")

We need to provide target entity type in `@OneToMany` and `@ManyToMany` decorators:

```
@OneToMany(() => Book, b => b.author)
books = new Collection<Book>(this);

@ManyToOne(() => Publisher, { ref: true })
publisher!: Ref<Publisher>;
```

#### Optional properties[​](#optional-properties "Direct link to Optional properties")

Reading property nullability is not supported, we need to explicitly set `nullable` attribute:

```
@Property({ nullable: true })
prop?: string;
```

#### Enums[​](#enums "Direct link to Enums")

By default, enum is considered as numeric type. For string enums, we need to explicitly provide one of:

* reference to the enum (which will force us to define the enum before defining the entity)
  <!-- -->
  ```
  @Enum(() => UserRole)
  role: UserRole;
  ```
* name of the enum (if it is present in the same file)
  <!-- -->
  ```
  @Enum({ type: 'UserRole' })
  role: UserRole;
  ```
* list of the enum items
  <!-- -->
  ```
  @Enum({ items: ['a', 'b', 'c'] })
  role: UserRole;
  ```

#### Circular dependencies[​](#circular-dependencies "Direct link to Circular dependencies")

Reading type of the referenced entity in `@ManyToOne` and `@OneToOne` properties may fail if there is circular dependency. You will need to explicitly define the type in the decorator (preferably via `entity: () => Author` callback).

```
@ManyToOne({ entity: () => Author })
author: Author;
```

When defining multiple entities in a single file, circular dependencies between those entities can also cause issues on type level, namely when using `reflect-metadata` provider. To get around those, you can use the `Rel` wrapper, which effectively disables `reflect-metadata`.

```
@ManyToOne({ entity: () => Author })
author: Rel<Author>;
```

This is also handy in ESM projects, where this problem can arise even when each entity resides in its own file.

#### Additional typings might be required[​](#additional-typings-might-be-required "Direct link to Additional typings might be required")

We might have to install additional typings, one example is use of `ObjectId` in MongoDB, which requires `@types/mongodb` to be installed.

## Using EntitySchema[​](#using-entityschema "Direct link to Using EntitySchema")

Alternatively, you can use [`EntitySchema`](https://mikro-orm.io/docs/entity-schema.md) instead, which is suitable for JavaScript only projects.

> If you want to have absolute control, you can also use `EntitySchema.fromMetadata()` factory method.

Read more about it in [Usage with JavaScript section](https://mikro-orm.io/docs/usage-with-js.md).