TLDR: How to create an interface for normalized data?
I'm building a React application using TypeScript. I use Normalizr to normalize the data from my API calls.
To give an example from the docs, an API response like this:
Quick 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"
}
}
]
}
Might be normalized to this:
{
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" }
}
}
}
I would like to create interfaces for my functions that use Normalizr. Here is what I've tried so far:
export interface House {
uuid: string;
address: string;
}
export interface Citizen {
uuid: string;
name: string;
}
export interface NormalizedData<T> {
[uuid: string]: T;
}
export interface Entity<T> {
[name: string]: NormalizedData<T>;
}
export interface NormalizerResult<T> {
result: any;
entities: Entity<T>;
}
Since I have to give a generic type T here, this approach can only handle one entity. The problem is that the entities key can have several entities of different types, eg. House and Citizen (and more). How would I account fo this? Normalizr's own types just give back { result: any, entities: any }
.
I guess you want something like this
export interface NormalizerResult<T extends House | Citizen> {
result: any;
entities: Entity<T>;
}
P.S. Typescript is more useful when you 100% know the structure of response and is less useful if response is different each time. If the former is correct, then you should make types for each response e.g.
export interface NormalizerResultForHousesAndCitizensRequest {
result: any;
entities: {
houses: NormalizedData<House>,
citizens: NormalizedData<Citizen>,
};
}