Skip to content

chore(types): start comprehensive typing #136

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed

Conversation

charliegroll
Copy link

Which problem is this pull request solving?

The type signatures could be improved to provide static checks to our typescript users that supplement our runtime checks.

List other issues or pull requests related to this problem

Noticed with #134

Describe the solution you've chosen

#134 disallows empty keys in the set functions at runtime, but I chose to infer what's passed in to those and disallow '' and strings that start with / at the type level.

Checklist

Please add a x inside each checkbox:

  • I have read the contribution guidelines.
  • The status checks are successful (continuous integration). Those can be seen below.

A picture of a cute animal (not mandatory but encouraged)

Happy Golden Retriever - RoBjhqlygXkCtgsWe6

@charliegroll charliegroll requested a review from a team as a code owner January 11, 2024 16:09
Copy link

netlify bot commented Jan 11, 2024

Deploy Preview for blobs-js ready!

Name Link
🔨 Latest commit f95ce3f
🔍 Latest deploy log https://app.netlify.com/sites/blobs-js/deploys/65a012b527b9610008ad165f
😎 Deploy Preview https://deploy-preview-136--blobs-js.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@github-actions github-actions bot added the type: chore work needed to keep the product and development running smoothly label Jan 11, 2024
@@ -19,6 +19,7 @@ interface NamedStoreOptions extends BaseStoreOptions {
}

export type StoreOptions = DeployStoreOptions | NamedStoreOptions
type Key<T> = T extends string ? (T extends '' | `/${string}` ? never : T) : never
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we want to go the route of stronger types, I'd love some input on naming conventions - this is more or less a POC/idea PR for consideration

Copy link
Contributor

@Skn0tt Skn0tt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unsure what to think about this idea, honestly. I like types like this when it comes to auto-completing static inputs, e.g. when frameworks use this to make their API discoverable. In this case, though, the key will often be something that stems from user input so it isn't static - and I worry that this can lead to hard-to-debug typescript errors, with little benefit at runtime.

@Skn0tt
Copy link
Contributor

Skn0tt commented Jan 11, 2024

What i'm not unsure on is the dog, though - that's a very cute doggo.

@charliegroll
Copy link
Author

the key will often be something that stems from user input

In the cases where they're static, like someone just playing with functions to learn our system or insert contrived example they could still get the benefit

I worry that this can lead to hard-to-debug typescript errors

I wonder if this is fair though because we can add doc blocks to the Key type and the set functions, and the types will be easily a cmd+click away

@Skn0tt
Copy link
Contributor

Skn0tt commented Jan 11, 2024

You commented out two type errors in the test suite. Both of them say Argument of type 'string' is not assignable to parameter of type 'never'., which is confusing to the not-so-TS-savvy user. Ideally, they'd say "key can't be empty" and "key can't start with a forward slash" instead, but that's not something doable with how these types work.

Essentially, we're trying to balance how much people are confused by this type error, against how much they gain by discovering a bug at type-check time as opposed to runtime.

Since we're only talking about statically analyzable inputs here, those runtime errors wouldn't depend on user input, so they'd occur pretty fast and probably during local dev.

On this tradeoff scale, my gut feeling is that the fancy types do more harm than good because the error messages are hard to read. But maybe there's a way of annotating the type with a custom error message?

@charliegroll
Copy link
Author

Thanks for the input @Skn0tt - until we get better ways to tell users "why never" it seems like this might not be worth it.

@charliegroll
Copy link
Author

I actually figured out after closing this that function overloads could provide a better experience

CleanShot 2024-01-11 at 10 25 10@2x

async set(key: `Key must not be empty and must not start with /`, data: BlobInput, opts?: SetOptions): Promise<void>
  async set<K>(key: Key<K>, data: BlobInput): Promise<void>
  async set<K>(key: Key<K>, data: BlobInput, { metadata }: SetOptions): Promise<void>
  async set<K>(key: Key<K>, data: BlobInput, { metadata }: SetOptions = {}) {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: chore work needed to keep the product and development running smoothly
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants