Browser Data Shapes
URL Query Shape
Browser query strings become small typed records before application code uses them.
query record
Parsing a query string into a record separates raw browser text from typed application data.
URL Query Shape
query.ts
Replay: real traced execution (multi-file project)
type QueryShape = {
page: number;
filter: string;
};
function readQuery(raw: string): QueryShape {
const pairs: string[] = raw.replace(/^\?/, "").split("&");
const values: Record<string, string> = {};
for (const pair of pairs) {
const [key, value] = pair.split("=");
values[key] = value;
}
return {
page: Number(values.page),
filter: values.filter
};
}
const pageText: string = "2";
const rawQuery: string = `?page=${pageText}&filter=active`;
const query: QueryShape = readQuery(rawQuery);
console.log(`${query.filter}:${query.page + 1}`);
type QueryShape = {
page: number;
filter: string;
};
function readQuery(raw: string): QueryShape {
const pairs: string[] = raw.replace(/^\?/, "").split("&");
const values: Record<string, string> = {};
for (const pair of pairs) {
const [key, value] = pair.split("=");
values[key] = value;
}
return {
page: Number(values.page),
filter: values.filter
};
}
const pageText: string = "5";
const rawQuery: string = `?page=${pageText}&filter=active`;
const query: QueryShape = readQuery(rawQuery);
console.log(`${query.filter}:${query.page + 1}`);
pageText ← 2, rawQuery ← ?page=2&filter=active
18 };19}2021const pageText→ 2: string = "2"; //@pageText="5"22const rawQuery→ ?page=2&filter=active: string = `?page=${pageText2}&filter=active`;23const query: QueryShape = readQuery(rawQuery?page=2&filter=active);pairs ← page=2,filter=active, values ← [object Object], key ← filter
3 filter: string;4};56function readQuery(raw?page=2&filter=active: string): QueryShape {7 const pairs→ page=2,filter=active: string[] = raw?page=2&filter=active.replace(/^\?/, "").split("&");8 const values→ [object Object]: Record<string, string> = {};910 for (const pair of pairs) {11 const [key→ filter, value→ active] = pairfilter=active.split("=");12 values[key] = valueactive;13 }1415 return {16 page: Number(values.page2),17 filter: values.filteractive18 };19}values this stepactivevalues[key]query ← [object Object], query.page ← 2
21const pageText: string = "2"; //@pageText="5"22const rawQuery: string = `?page=${pageText}&filter=active`;23const query→ [object Object]: QueryShape = readQuery(rawQuery?page=2&filter=active);2425console.log(`${query.filteractive}:${query.page→ 2 + 1}`);outputactive:3
pageText ← 5, rawQuery ← ?page=5&filter=active
18 };19}2021const pageText→ 5: string = "5";22const rawQuery→ ?page=5&filter=active: string = `?page=${pageText5}&filter=active`;23const query: QueryShape = readQuery(rawQuery?page=5&filter=active);pairs ← page=5,filter=active, values ← [object Object], key ← filter
3 filter: string;4};56function readQuery(raw?page=5&filter=active: string): QueryShape {7 const pairs→ page=5,filter=active: string[] = raw?page=5&filter=active.replace(/^\?/, "").split("&");8 const values→ [object Object]: Record<string, string> = {};910 for (const pair of pairs) {11 const [key→ filter, value→ active] = pairfilter=active.split("=");12 values[key] = valueactive;13 }1415 return {16 page: Number(values.page5),17 filter: values.filteractive18 };19}values this stepactivevalues[key]query ← [object Object], query.page ← 5
21const pageText: string = "5";22const rawQuery: string = `?page=${pageText}&filter=active`;23const query→ [object Object]: QueryShape = readQuery(rawQuery?page=5&filter=active);2425console.log(`${query.filteractive}:${query.page→ 5 + 1}`);outputactive:6