A thing or two about type safety
See original GitHub issueHey, so on the discord server @postspectacular told me about the typesafe versions of paths. I took a look and I was not so happy to see this giant mess (it’s actually a lot more but if I make the text even smaller it becomes hard to read):
Based on the fact those things are imported from @thi.ng/api
I’m pretty sure other packages contain code like this as well… But we can do more! Typescript has a pretty neat type system which allows us to write stuff like that without all the repetition!
Final result:
Before going into more details, here’s the final result of the refactor for the code above:
And the good thing is, this works for any path length!
Building blocks:
To be able to achive that I had to write a few basic types:
Note: In case you want to see the actual implementations of the types you can take a look at this typescript playground link
- Head: returns the first element of a tuple:
type HeadTest1 = Head<[1, 2, 3]>; // 1
type HeadTest2 = Head<[]>; // never
type HeadTest3 = Head<"not an array">; // never
- Tail: returns everything except the first element of a tuple:
type TailTest1 = Tail<[1, 2, 3]>; // [2, 3]
type TailTest2 = Tail<[]>; // []
type TailTest3 = Tail<"not an array">; // never
- Concat: Tried adding an item at the start of a tuple:
type ConcatTest1 = Concat<0, [1, 2, 3]>; // [0, 1, 2, 3]
type ConcatTest2 = Concat<0, "not an array">; // never
- Reverse: pretty explanatory name, reverses the order of elements of a tuple:
type ReverseTest1 = Reverse<[1, 2, 3]>; // [3,2,1]
type ReverseTest2 = Reverse<[]> // []
type ReverseTest3 = Reverse<"not an array"> // never
Those are the building blocks for a lot of more complex types.
Question 1: where should I add these? (I’m thinking of @thi.ng/api
but I’m not sure
The actual path stuff
Appying the same logic I was able to build a path validator and a path applier which work with any amount of nesting:
interface Nested {
a: {
b: {
c: number;
};
};
}
type Test1 = ValidatePath<Nested, ["a", "b"]>; // ["a","b"]
type Test2 = ValidatePath<Nested, ["a", "d"]>; // never
type Test3 = RetrivePath<Nested, Test1>; // { c: number }
type Test4 = RetrivePath<Nested, Test2>; // never
Question 2: Does this seem interesting? Should I open a PR making the entire lib use it?
Note: The paths package was just an example, this could be applied to a lot of other stuff!!!
So, let’s discuss it! What do yall think of this method of typing? Should I open PRs with it?
Issue Analytics
- State:
- Created 4 years ago
- Reactions:2
- Comments:9 (8 by maintainers)
Top GitHub Comments
Great idea
I think we can close this