0.4.0 • Published 4 years ago
ts-norm v0.4.0
ts-norm
A normalizr like library for TypeScript.
🙏Pull requests are welcome!
Installation
yarn add ts-normnpm install ts-normQuick Start
Consider a typical blog post. The API response for a single post might look something like this:
{
  "id": "123",
  "author": {
    "id": "1",
    "name": "Paul"
  },
  "title": "My awesome blog post",
  "comments": [
    {
      "id": "324",
      "commenter": {
        "id": "2",
        "name": "Nicole"
      }
    }
  ]
}We have two nested entity types within our article: users and comments. Using various schema, we can normalize all three entity types down:
import { normalize, denormalize, schema, Dictionary } from "ts-norm";
type User = {
  id: string;
  name: string;
};
type Comment = {
  id: string;
  commenter: User;
};
type Article = {
  id: string;
  author: User;
  title: string;
  comments: Comment[];
};
// Define a users schema
const user = schema<User>().entity("users");
// Define your comments schema
const comment = schema<Comment>().entity("comments", {
  commenter: user,
});
// Define your article
const article = schema<Article>().entity("articles", {
  author: user,
  comments: [comment],
});
const normalizedData = normalize(originalData, article);
const denormalizedData = denormalize(
  normalizedData.result,
  article,
  normalizedData.entities
);
type Expected = {
  result: string;
  entities: {
    users: Dictionary<{ id: string; name: string }>;
    comments: Dictionary<{ id: string; commenter: string }>;
    articles: Dictionary<{
      id: string;
      author: string;
      title: string;
      comments: string[];
    }>;
  };
};
// Type Safe!!
function expectType<T>(_: T) {}
expectType<Expected>(normalizedData);
expectType<Article>(denormalizedData);Now, normalizedData will be:
{
  "result": "123",
  "entities": {
    "articles": {
      "123": {
        "id": "123",
        "author": "1",
        "title": "My awesome blog post",
        "comments": ["324"]
      }
    },
    "users": {
      "1": { "id": "1", "name": "Paul" },
      "2": { "id": "2", "name": "Nicole" }
    },
    "comments": {
      "324": { "id": "324", "commenter": "2" }
    }
  }
}With idAttribute & generateId
type User = {
  name: string;
};
type Article = {
  title: string;
  author: User;
};
const user = schema<User>().entity(
  "users",
  {},
  {
    idAttribute: "userId",
    generateId: (): string => uuid(),
  }
);
const article = schema<Article>().entity(
  "articles",
  { author: user },
  {
    idAttribute: "articleId",
    generateId: (): number => counter(),
  }
);
const normalizedData = normalize(originalData, article);
type Expected = {
  result: number;
  entities: {
    users: Dictionary<{
      userId: string;
      name: string;
    }>;
    articles: Dictionary<{
      articleId: number;
      title: string;
      author: string;
    }>;
  };
};
function expectType(_: Expected) {}
expectType(normalizedData);