From 47bc8b167287110287e03314021040ab6cba397e Mon Sep 17 00:00:00 2001 From: Inga Date: Thu, 8 Feb 2024 22:51:07 +0000 Subject: [PATCH] tmp --- sitemap-parser/src/createSitemap.spec.ts | 22 +++++++++++++++-- sitemap-parser/src/createSitemap.ts | 31 +++++++++++++++++++++--- sitemap-parser/src/resolveByPath.ts | 13 +++++----- sitemap-parser/src/types.ts | 29 +++++++++++++++++++--- 4 files changed, 81 insertions(+), 14 deletions(-) diff --git a/sitemap-parser/src/createSitemap.spec.ts b/sitemap-parser/src/createSitemap.spec.ts index 7960731..8ea0d5e 100644 --- a/sitemap-parser/src/createSitemap.spec.ts +++ b/sitemap-parser/src/createSitemap.spec.ts @@ -1,5 +1,5 @@ -import { createSitemap } from './createSitemap'; -import { ApiResponse, Sitemap } from './types'; +import { TypedSitemap, createSitemap } from './createSitemap'; +import { ApiResponse, PathsResolver, Paths, ResolverForPaths, Sitemap, Simplify } from './types'; describe('createSitemap', () => { it('creates correct sitemap for sample data', () => { @@ -16,6 +16,24 @@ describe('createSitemap', () => { { id: 10, slug: 'children', parent: 8 }, ] as const satisfies ApiResponse; + const x: TypedSitemap = null as any; + const y: Simplify> = null as any; + if (y[0] === '/') { + let f = y[1] + } + const z: ResolverForPaths = null as any; + const a = z('/books/children') + const b = z('huihuoj'); + const z2: PathsResolver = null as any; + const m = z2('/'); + //const c = z2(''); + const d = z2('abc'); + const e = z2('/'); + //const z: Sitemap = x; + + const f = sampleInput as ApiResponse; + const g: TypedSitemap = null as any; + const sampleOutput = { name: 'root', id: 1, diff --git a/sitemap-parser/src/createSitemap.ts b/sitemap-parser/src/createSitemap.ts index ffe64a2..f7e89db 100644 --- a/sitemap-parser/src/createSitemap.ts +++ b/sitemap-parser/src/createSitemap.ts @@ -1,4 +1,4 @@ -import { ApiResponse, Sitemap } from './types'; +import { ApiResponse, Sitemap, Simplify } from './types'; type Subtree = { name: string; @@ -6,10 +6,35 @@ type Subtree = { children: Sitemap[]; }; +type GetBaseParentIdType = TParentId extends null ? null : number; + +type ExtractEntryByParentId = + //Extract; + Simplify<{ readonly parent: GetBaseParentIdType } extends Pick ? TEntry : Extract>; + +type ExtractEntriesByParentId = ExtractEntryByParentId; + +type TypedSitemapEntry = TEntry extends unknown ? { + name: TEntry['slug'], + id: TEntry['id'], + children: TypedSitemapEntries +} : never; + +type TypedSitemapEntries = TypedSitemapEntry>[]; + +//type NeverToNull = TSitemap extends never ? null : TSitemap; + +//export type TypedSitemap = Simplify[number]>>>; +export type TypedSitemap = Simplify[number]>; + +//const z = [{slug: 'a', id: 1, parent: 1 }]; +//type Q = NeverToNull>; +//type A = never extends never ? 'a' : 'b'; + // alternatively, for full TS experience, if I had more time I'd also implement parsing in TS so that this declaration would look like: // export const createSitemap = (apiResponse: TResponse): Sitemap => { // and calling e.g. `createSitemap(const sample data json)` would return value with type `const sample sitemap`, rather than just general sitemap -export const createSitemap = (apiResponse: ApiResponse): Sitemap | null => { +export const createSitemap = (apiResponse: ApiResponse): TypedSitemap => { const subtrees = new Map( apiResponse.map(({ id, slug }) => [ id, @@ -36,5 +61,5 @@ export const createSitemap = (apiResponse: ApiResponse): Sitemap | null => { } } - return root; + return root as any; }; diff --git a/sitemap-parser/src/resolveByPath.ts b/sitemap-parser/src/resolveByPath.ts index 704e0a6..9697d7e 100644 --- a/sitemap-parser/src/resolveByPath.ts +++ b/sitemap-parser/src/resolveByPath.ts @@ -16,19 +16,20 @@ import { Sitemap } from './types'; ); };*/ -const createPaths = (node: Sitemap): Readonly<[string, number]>[] => [ - ['', node.id], +const createPaths = ( + node: Sitemap, + prefix: string, +): Readonly<[string, number]>[] => [ + [prefix, node.id], ...node.children.flatMap((childNode) => - createPaths(childNode).map( - ([path, id]) => [`/${childNode.name}${path}`, id] as const, - ), + createPaths(childNode, `${prefix}/${childNode.name}`), ), ]; // Second, improved implementation, where we build a static hashmap from complete paths to IDs once, // and then use it as a single lookup table. export const createPathResolver = (sitemap: Sitemap | null) => { - const rawPathsData = sitemap ? createPaths(sitemap) : []; + const rawPathsData = sitemap ? createPaths(sitemap, '') : []; const pathsMap = new Map( rawPathsData.map(([path, id]) => [path.length ? path : '/', id]), ); diff --git a/sitemap-parser/src/types.ts b/sitemap-parser/src/types.ts index c381e55..b74ecb0 100644 --- a/sitemap-parser/src/types.ts +++ b/sitemap-parser/src/types.ts @@ -7,7 +7,30 @@ export type ApiResponse = Readonly< >; export type Sitemap = Readonly<{ - name: string; - id: number; - children: readonly Sitemap[]; + readonly name: string; + readonly id: number; + readonly children: readonly Sitemap[]; }>; + +export type Simplify = T extends Record | unknown[] + ? T extends infer O + ? { [K in keyof O]: Simplify } + : never + : T; + +type PathsForEntry = TEntry extends unknown ? [`${TPrefix}/${TEntry['name']}`, TEntry['id']] | PathsForEntry : never; + +export type Paths = Simplify | ['/', TSitemap['id']]>; + +type Mew = T extends readonly [string, number] ? T : never; + +type ResetStack = T extends infer R ? R & readonly [string, number] : never; + +export type ResolverForPaths = { + (path: TPath): Extract[1]; + (unknownPath: string): null; +}; + +export type PathsResolver = ResolverForPaths extends infer R ? R : never, readonly [string, number]>>; + +//export type PathsResolver = ResolverForPaths>;