You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Part of umbrella issue #16. Cannot be started until #108 and #110 are done.
Realistically, this is going to be, by far, the hardest part of the entire umbrella issue. Depending on how things go, we might have to abandon it, or turn it into something that gets chipped away at over time.
If we're not careful, I could see this using up a lot of working hours, which is why I think it should always be treated as a lower-priority issue. This could end up being on the level of our type-generation logic in the main Coder codebase. Expect to need to pay a visit to Matt Pocock's TypeScript Wizards Discord server for help
Problem
Let's say that #108 is done, and we have CoderClient.arbitraryApiCall defined, and ready to go. There's just one problem: the method isn't really type-safe at all. The method needs to be able to work with any kind of data, so it always return type Promise<any>, and while you can add type parameters to make things more specific, specificity doesn't translate to more accuracy. The type parameters rely entirely on user input – it's easy to make a typo and pass in the wrong parameter, and TypeScript won't let you know. You'll only realize your mistake after having a runtime error
So, why not make a wrapper over the method which will bring in that type safety? The core logic will still live in the method, but the hook will provide a lot of TypeScript magic to catch typos and other mistakes, while addressing some React-specific gotchas
Requirements
The hook does not have much runtime logic at all – the vast majority of it is deferred to CoderClient.arbitraryApiCall
Additional runtime values should only be introduced if it helps remove React gotchas and footguns
The "TS magic" is that the hook will accept a config object as input, and depending on the values in that input, that will inform the return type of the function you get back
For example:
// Without a single type annotation, TypeScript knows that the return type is// Promise<Workspace>, that it needs a JSON body to make the workspace,// and that it needs a full endpoint that matches the pattern:// `/organizations/${string}/members/${string}/workspaces`// TypeScript will enforce this pattern and catch typos.// More importantly, the hook is aware of every method-endpoint combo, and// will reject anything it isn't aware ofconstmakeWorkspace=useCoderApiFunction({method: "POST",endpoint: "/organizations/:organizationId/members/:memberId/workspaces"});// If anything differs from this precise arrangement of endpoint and body,// TypeScript will catch that. If we passed in an endpoint that doesn't have// dynamic parameter segments (defined via ":"), it would be smart enoughconstnewWorkspace=awaitmakeWorkspace({endpoint: `/organizations/${orgId}/members/${memberId}/workspaces`body: jsonBodyForWorkspaces,});
The hook only demands the bare minimum from the user – it only asks for information it doesn't already have
Put another way, if the hook's returned-out function can safely reuse any of the arguments the hook received as input, it should do that. The function should not require that information again when the user actually calls the function
The memory reference of the exported function should always remain stable, even if the inputs fed into it change across re-renders
Someone should be able to throw this into a useEffect call without (1) lying about their dependencies or (2) making the hook trigger any infinite loops
My main worry is that this could be absolutely horrific for VS Code performance, and could slow down the entire client, whenever the user just happens to have the Coder plugin imported. See "Unknowns and Pitfalls" section below
We could figure out a way to generate every endpoint-method permutation via codegen.
Every permutation, and its associated hook inputs + API function inputs could be defined as more lightweight function overloads. This is most likely to scale, but we're getting into the same territory as the type generation we use for the main Coder codebase
Unknowns and pitfalls
If we're not careful with how the code is defined, this single hook could end up bringing VS Code's entire TypeScript LSP (Language Server Protocol) to its knees, and cause it to constantly crash
And because there is no way to interact with the type system directly, much less optimize it, there might not even be a good way to define this logic dynamically using traditional TypeScript types
If performance gets so bad that that traditional types would be impossible, we would either have to (1) give up on this, or (2) go the codegen route
The text was updated successfully, but these errors were encountered:
Part of umbrella issue #16. Cannot be started until #108 and #110 are done.
Realistically, this is going to be, by far, the hardest part of the entire umbrella issue. Depending on how things go, we might have to abandon it, or turn it into something that gets chipped away at over time.
If we're not careful, I could see this using up a lot of working hours, which is why I think it should always be treated as a lower-priority issue. This could end up being on the level of our type-generation logic in the main Coder codebase. Expect to need to pay a visit to Matt Pocock's TypeScript Wizards Discord server for help
Problem
Let's say that #108 is done, and we have
CoderClient.arbitraryApiCall
defined, and ready to go. There's just one problem: the method isn't really type-safe at all. The method needs to be able to work with any kind of data, so it always return typePromise<any>
, and while you can add type parameters to make things more specific, specificity doesn't translate to more accuracy. The type parameters rely entirely on user input – it's easy to make a typo and pass in the wrong parameter, and TypeScript won't let you know. You'll only realize your mistake after having a runtime errorSo, why not make a wrapper over the method which will bring in that type safety? The core logic will still live in the method, but the hook will provide a lot of TypeScript magic to catch typos and other mistakes, while addressing some React-specific gotchas
Requirements
CoderClient.arbitraryApiCall
useEffect
call without (1) lying about their dependencies or (2) making the hook trigger any infinite loopsPossible solutions
Unknowns and pitfalls
The text was updated successfully, but these errors were encountered: