Created
June 17, 2020 10:19
-
-
Save waynevanson/64422549f92d3b6e90d2d1dccbacd05f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
FREE TO USE! COPY AND PASTE INTO YOUR PROJECT. TELL YOUR FRIENDS ABOUT MAPPABLE TYPES! | |
How to use: | |
install dependencies (tree shakable): | |
`yarn add fp-ts ts-toolbelt normalizr` | |
Your schema definitions should look like this: | |
```ts | |
export type Axis = { id: string; cells: Cell[] }; | |
export type Row = Axis; | |
export type Column = Axis; | |
export type Cell = { id: string; text: string }; | |
export const cells = new normalizr_schema.Entity<Cell>("cells"); | |
export const columns = new normalizr_schema.Entity<Column>("columns", { | |
cells: [cells], | |
}); | |
export const rows = new normalizr_schema.Entity<Row>("rows", { | |
cells: [cells], | |
}); | |
export const schema = { | |
cells: [cells], | |
columns: [columns], | |
rows: [rows], | |
}; | |
``` | |
*/ | |
import { record } from "fp-ts"; | |
import { pipe } from "fp-ts/lib/function"; | |
import { | |
denormalize as _denormalize, | |
normalize as _normalize, | |
schema, | |
} from "normalizr"; | |
import { A } from "ts-toolbelt"; | |
export type InputSchema = Record<string, schema.Entity[]>; | |
export type NormalizeData<R extends InputSchema> = A.Compute< | |
EntitiesSchemaToDataType<R> | |
>; | |
export type NormalizeResult<R extends InputSchema> = A.Compute< | |
EntitiesFlatten<R> | |
>; | |
export function normalize< | |
R extends InputSchema, | |
D extends NormalizeData<R>, | |
N extends NormalizeResult<R> | |
>(schema: R, data: D): N { | |
return _normalize(data, schema).entities as N; | |
} | |
export function denormalize<R extends InputSchema>(schema: R) { | |
return ( | |
state: A.Compute<EntitiesFlatten<R>>, | |
recordIds: Partial<{ [P in keyof R]: string[] }> | |
) => { | |
const empty = pipe( | |
schema, | |
record.map(() => [] as string[]), | |
(a) => ({ ...a, ...recordIds }) | |
); | |
return _denormalize(empty, schema, state) as A.Compute< | |
EntitiesSchemaToDataType<R> | |
>; | |
}; | |
} | |
export type FlattenUnion<T extends object> = { | |
[P in keyof T]: T[P] extends Array<infer U> | |
? U extends object | |
? Array<string | U> | |
: never | |
: T[P] extends object | |
? string | T[P] | |
: T[P]; | |
}; | |
export type Flatten<T extends object> = { | |
[P in keyof T]: T[P] extends Array<infer U> | |
? U extends object | |
? Array<string> | |
: never | |
: T[P] extends object | |
? string | |
: T[P]; | |
}; | |
export type EntitiesSchemaToDataType<S extends InputSchema> = { | |
[P in keyof S]: S[P] extends schema.Entity<infer T>[] | |
? T extends object | |
? FlattenUnion<T>[] | |
: never | |
: never; | |
}; | |
export type EntitiesFlatten<S extends InputSchema> = { | |
[P in keyof S]: S[P] extends schema.Entity<infer T>[] | |
? T extends object | |
? Record<string, Flatten<T>> | |
: never | |
: never; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment