diff --git a/src/Resources/views/common.ts.twig b/src/Resources/views/common.ts.twig
index b88fe462151980d33345090dfde344ae11270f1b..9ba8bef01f2c0fea8508380038d3450b76df238f 100644
--- a/src/Resources/views/common.ts.twig
+++ b/src/Resources/views/common.ts.twig
@@ -25,10 +25,18 @@ const IRI = Symbol('IRI');
  * IRI et chaînes, et le type générique R permet d'interdire les assignations entre
  * IRI de resources différentes.
  */
-export interface IRI<R> {
-  readonly [ IRI ]?: R;
+export interface IRI<R extends Resource> {
+  readonly [IRI]?: R;
 }
 
+/**
+ * Resource
+ */
+export interface Resource {
+  readonly [IRI_PROPERTY]: IRI<any>;
+  readonly [TYPE_PROPERTY]: string;
+  [property: string]: any;
+};
 
 /**
  * Collection représente une collection de respoucres JSON-LD pour un type T donné.
@@ -73,7 +81,7 @@ export abstract class AbstractResourceCache {
    * Récupère une ressource par son IRI. N'exécute la requête requestFactory que si on ne dispose
    * pas d'une version en cache.
    */
-  public abstract get<R extends { readonly [IRI_PROPERTY]: IRI<any> }>(
+  public abstract get<R extends Resource>(
     iri: IRI<R>,
     requestFactory: () => Observable<R>
   ): Observable<R>;
@@ -81,29 +89,29 @@ export abstract class AbstractResourceCache {
   /**
    * Met à jour une ressource existante, rafraîchit le cache local avec la réponse.
    */
-  public abstract put<R>(iri: IRI<R>, request: Observable<R>): Observable<R>;
+  public abstract put<R extends Resource>(iri: IRI<R>, request: Observable<R>): Observable<R>;
 
   /**
    * Crée une nouvelle ressource et met la ressource créée dans le cache.
    */
-  public abstract post<R extends { readonly [IRI_PROPERTY]: IRI<any> }>(request: Observable<R>): Observable<R>;
+  public abstract post<R extends Resource>(request: Observable<R>): Observable<R>;
 
   /**
    * Supprime une ressource en distant et dans le cache.
    */
-  public abstract delete<R>(iri: IRI<R>, request: Observable<HttpResponseBase>): Observable<HttpResponseBase>;
+  public abstract delete<R extends Resource>(iri: IRI<R>, request: Observable<HttpResponseBase>): Observable<HttpResponseBase>;
 
   /**
    * Effectue une recherche et met en cache toutes les ressources récupérées.
    */
-  public abstract getAll<R extends { readonly [IRI_PROPERTY]: IRI<any> }>(
+  public abstract getAll<R extends Resource>(
     request: Observable<Collection<R>>
   ): Observable<Collection<R>>;
 
   /**
    * Invalide une ressource en cache.
    */
-  public abstract invalidate<R>(iri: IRI<R>): void;
+  public abstract invalidate<R extends Resource>(iri: IRI<R>): void;
 }
 
 /**
@@ -144,7 +152,7 @@ function getResourceType(that: any): string | null {
  * R : type de resource, e.g. Person
  * T : valeur de la propriété '@type', e.g. 'Person'.
  */
-export class ResourceMetadata<R, T> {
+export class ResourceMetadata<R extends Resource, T extends string> {
   public constructor(
     public readonly type: T,
     private readonly iri: IRIMetadata<any>,
@@ -176,7 +184,7 @@ export class ResourceMetadata<R, T> {
 /**
  * Classe de base d'un repository.
  */
-export abstract class AbstractRepository<R, T> {
+export abstract class AbstractRepository<R extends Resource, T extends string> {
   public constructor(
     public readonly metadata: ResourceMetadata<R, T>,
     protected readonly client: HttpClient,
diff --git a/src/Resources/views/metadata.ts.twig b/src/Resources/views/metadata.ts.twig
index c9ffbfe5438307575d6a0195ebc2531eb45f6c68..e707691099a6d83a456a5352bd7c56826b8c674e 100644
--- a/src/Resources/views/metadata.ts.twig
+++ b/src/Resources/views/metadata.ts.twig
@@ -2,11 +2,11 @@
 
 {% block content %}
 {% autoescape false %}
-import { Injectable } from '@angular/core';
+import { Injectable, Provider } from '@angular/core';
 import { Observable } from 'rxjs';
 import { HttpClient } from '@angular/common/http';
 
-import { IRI, AbstractResourceCache, IRIMetadata, ResourceMetadata, UUID, IRI_PROPERTY } from './common';
+import { IRI, AbstractResourceCache, IRIMetadata, ResourceMetadata, UUID, IRI_PROPERTY, TYPE_PROPERTY, Resource } from './common';
 import {
 {% for repo in repositories %}
   {{ repo.resourceName }}{% if not loop.last %},{% endif %}
@@ -125,11 +125,11 @@ export class API {
     return this[type];
   }
 
-  public get<R extends { [IRI_PROPERTY]: IRI<R> }>(iri: IRI<R>): Observable<R> {
+  public get<R extends Resource>(iri: IRI<R>): Observable<R> {
     return this.cache.get(iri, () => this.client.get<R>(iri as any));
   }
 
-  public invalidate(iri: IRI<any>): void {
+  public invalidate<R extends Resource>(iri: IRI<R>): void {
     this.cache.invalidate(iri);
   }
 }
@@ -142,11 +142,11 @@ export function {{ repo.usage }}Factory(api: API): {{ repo.usage }} { return api
 /**
  * Providers Angular
  */
-export const PROVIDERS = [
+export const PROVIDERS: Provider[] = [
   MetadataRegistry,
   API,
 {% for repo in repositories %}
-  { provides: {{ repo.usage  }}, useFactory: {{ repo.usage }}Factory, deps: [API] },
+  { provide: {{ repo.usage  }}, useFactory: {{ repo.usage }}Factory, deps: [API] },
 {% endfor %}
 ];