Skip to content

Commit 106d747

Browse files
committed
scratch work on deriving the params object type from the string passed as the path spec
it all works except that we also take the returned value type as a type parameter, and typescript won't infer the pathspec string type to the literal passed if you pass the return type. its both or neither. when microsoft/TypeScript#26349 is merged, this should work
1 parent 02b7061 commit 106d747

File tree

1 file changed

+83
-4
lines changed

1 file changed

+83
-4
lines changed

new/src/firebase-recoil/index.ts

+83-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
import { atom, AtomEffect, atomFamily, RecoilState } from "recoil";
1+
import {
2+
atom,
3+
AtomEffect,
4+
atomFamily,
5+
RecoilState,
6+
type SerializableParam,
7+
} from "recoil";
28
import { Database, DataSnapshot, ref, onValue, get } from "firebase/database";
39
import { interpolatePathSpec, PathParameters } from "./interpolatePathSpec";
410
import type { FirebaseArray } from "../firebase/types";
@@ -36,13 +42,86 @@ export function makeAtom<T extends FirebaseValue>(
3642
});
3743
}
3844

45+
type PP<K extends string> = {
46+
[Property in K]: string;
47+
};
48+
49+
function test<T extends string>(pathSpec: string, args: PP<T>): string {
50+
return "hi";
51+
}
52+
53+
const x = test<"key1" | "key2">("ok", { key1: "hi", key2: "hi" });
54+
55+
type IsParameter<Part> = Part extends `{${infer ParamName}}`
56+
? ParamName
57+
: never;
58+
type FilteredParts<Path> = Path extends `${infer PartA}/${infer PartB}`
59+
? IsParameter<PartA> | FilteredParts<PartB>
60+
: IsParameter<Path>;
61+
type ParamValue<Key> = Key extends `...${infer Anything}` ? string[] : string;
62+
type RemovePrefixDots<Key> = Key extends `...${infer Name}` ? Name : Key;
63+
type Params<Path> = {
64+
[Key in FilteredParts<Path> as RemovePrefixDots<Key>]: ParamValue<Key>;
65+
};
66+
type CallbackFn<Path> = (req: { params: Params<Path> }) => void;
67+
68+
function get2<Path extends string = string>(
69+
path: Path,
70+
callback: CallbackFn<Path>
71+
) {
72+
// TODO: implement
73+
}
74+
75+
function make2<Path extends string = string>(path: Path): CallbackFn<Path> {
76+
return (req) => {};
77+
}
78+
79+
const makeCallback = make2("/hi/{there}/cool")({ params: { there: "hi" } });
80+
81+
get2("hi/{there}/cool", ({ params: { there } }) => {});
82+
83+
const db: Database = {};
84+
85+
const af = makeAtomFamily("/hi/{there}/cool", db);
86+
af({ there: "ok" });
87+
af({ shouldFail: "ok" });
88+
89+
//https://github.com/microsoft/TypeScript/pull/26349
90+
const af2 = makeAtomFamily<number>("/hi/{there}/cool", db);
91+
af2({ there: "ok" });
92+
af2({ shouldFail: "ok" });
93+
94+
function omg<T extends string, N extends number>(t: T, n: N): { x: T; y: N } {
95+
return { x: t, y: n };
96+
}
97+
98+
omg("cool", 3);
99+
// omg<string>("ok", 2);
100+
101+
export function makeAtomFamilyMaker<T extends FirebaseValue>(
102+
database: Database
103+
): <Path extends string>(
104+
pathSpec: Path,
105+
database: Database
106+
) => (pathSpec: Path) => RecoilState<T> {
107+
return (pathSpec) => makeAtomFamily(pathSpec, database);
108+
}
109+
110+
type KnownPathSpecAtomMaker<T extends FirebaseValue> = <T>() => RecoilState<T>;
111+
112+
export function otherWay<Path extends string>(
113+
pathSpec: Path,
114+
database: Database
115+
): KnownPathSpecAtomMaker<T> {}
116+
39117
export function makeAtomFamily<
40118
T extends FirebaseValue,
41-
P extends PathParameters
42-
>(pathSpec: string, database: Database): (param: P) => RecoilState<T> {
119+
Path extends string
120+
// P extends Params<Path> & SerializableParam = Params<Path>
121+
>(pathSpec: Path, database: Database): (param: Params<Path>) => RecoilState<T> {
43122
// TODO if we have some unique id for the app, we can include in the key
44123
// and support multiple firebase connections
45-
return atomFamily<T, P>({
124+
return atomFamily<T, Params<Path>>({
46125
key: `firebase-recoil:${pathSpec}`,
47126
effects: (params) => [
48127
// TODO what would happen if we threw an exception here?

0 commit comments

Comments
 (0)