8000 Maybe the opaque types are too opaque · Issue #459 · anza-xyz/kit · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Maybe the opaque types are too opaque #459

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
steveluscher opened this issue May 5, 2025 · 5 comments · Fixed by #473
Closed

Maybe the opaque types are too opaque #459

steveluscher opened this issue May 5, 2025 · 5 comments · Fixed by #473
Labels
enhancement New feature or request

Comments

@steveluscher
Copy link
Collaborator

Motivation

We're about to take this library to v3 and beyond with some breaking changes. It occurs to me that despite being structurally identical between v2 and v3, types based on unique symbol like Address will start to mismatch between the two.

Example use case

Imagine someone trying to use an Address between different versions of @solana/kit. They're absolutely runtime compatible, but the type incompatibility between two versions of unique symbol is demonstrated by this playground (link).

Proposal

In the next major version (3.0.0) modify all of the branded types to fit this pattern:

type Foo = T & { ['__@solana/kit;brand']: 'Foo' };

Playground (link)

@steveluscher steveluscher added the enhancement New feature or request label May 5, 2025
@jordaaash
Copy link

nit: '__@solana/kit;brand' reads a bit confusing to me. __brand:@solana/kit is a bit easier to parse, but __@solana/kit__ is probably fine on its own. On the other hand, there's always ['@solana/kit:INTERNAL_DO_NOT_USE_OR_YOU_WILL_BE_FIRED'] 😄

Since this becomes pretty verbose, a reusable utility type of

// @internal
export type SolanaKitBrand<T, B> = T & { readonly ['<whatever>']: B };

could help (at the cost of importing this in a bunch of places).

@lorisleiva
Copy link
Member

I love this and I agree with Jordan's notation.

unique symbol is a great TypeScript feature but the reality is, when exporting multiple versions (even within the same major version) for multiple environments, it's not super robust.

We're already running into issues where package managers decide to use multiple type definitions of the same package within the same dependency tree causing really annoying bugs to debug if you don't recognise them. This is already happening to us on program clients as dependabot will often only upgrade part of the lock file, leaving other linked dependencies untouched.

@alannza
Copy link
Contributor
alannza commented May 7, 2025

I have barely touched symbols but I've lightly used branding in the past and not had issues.

Imagine someone trying to use an Address between different versions of @solana/kit.

Can you say more? Are you worried people will have literally two major versions of @solana/kit loaded into the same app, and then try and pass data back and forth? Or are things being serialized/deserialized between them somehow?

@steveluscher
Copy link
Collaborator Author

Are you worried people will have literally two major versions of @solana/kit loaded into the same app, and then try and pass data back and forth?

I am. I'm thinking of a world where something like Orca's SDK specifies v2 but someone decides to go to the v3 that we're about to tag this month. Depending on the package manager and the state of folks' lockfiles, I could imagine people ending up with two copies of (eg.) @solana/addresses.

steveluscher added a commit that referenced this issue May 8, 2025
#### Problem

Two versions of any given package may introduce two distinct instances of our branded types into a project. That is to say you might get the `Address` type from v2.1.0 and v3.0.0 in the same project.

When this happens, you will end up with values that are runtime identical, but whose types mismatch. This is because the way we brand the types involves `unique symbol` which is locally unique to the particular instance of the package being imported.

#### Summary of Changes

Create a package with utilities that will brand types with shared names across the entire project, instead of unique symbols that are module-local.

Addresses #459
steveluscher added a commit that referenced this issue May 8, 2025
…lly similar type from any package version, going forward (#473)

#### Problem

Two versions of any given package may introduce two distinct instances of our branded types into a project. That is to say you might get the `Address` type from v2.0.0 and v2.1.0 in the same project.

#### Summary of Changes

Here we use the type utilities in the previous stacked PR to reimagine these types as structurally identical, rather than having an identity that's tied to one particular instance of a module.

This will make it so that `Address` and other branded types like it are compatible from version v2.1.1 and onward.

Fixes #459
Copy link
Contributor

Because there has been no activity on this issue for 7 days since it was closed, it has been automatically locked. Please open a new issue if it requires a follow up.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 16, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request
Projects
None yet
4 participants
0