Skip to content

Conversation

@Patrick-Pimentel-Bitwarden
Copy link
Contributor

@Patrick-Pimentel-Bitwarden Patrick-Pimentel-Bitwarden commented Apr 25, 2025

🎟️ Tracking

📔 Objective

Adding documentation to point to when making the change for enums.

⏰ Reminders before review

  • Contributor guidelines followed
  • All formatters and local linters executed and passed
  • Written new unit and / or integration tests where applicable
  • Protected functional changes with optionality (feature flags)
  • Used internationalization (i18n) for all UI strings
  • CI builds passed
  • Communicated to DevOps any deployment requirements
  • Updated any necessary documentation (Confluence, contributing docs) or informed the documentation
    team

🦮 Reviewer guidelines

  • 👍 (:+1:) or similar for great changes
  • 📝 (:memo:) or ℹ️ (:information_source:) for notes or general info
  • ❓ (:question:) for questions
  • 🤔 (:thinking:) or 💭 (:thought_balloon:) for more open inquiry that's not quite a confirmed
    issue and could potentially benefit from discussion
  • 🎨 (:art:) for suggestions / improvements
  • ❌ (:x:) or ⚠️ (:warning:) for more significant problems or concerns needing attention
  • 🌱 (:seedling:) or ♻️ (:recycle:) for future improvements or indications of technical debt
  • ⛏ (:pick:) for minor or nitpick changes

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Apr 25, 2025

Deploying contributing-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: 69a927a
Status: ✅  Deploy successful!
Preview URL: https://0512c9c6.contributing-docs.pages.dev
Branch Preview URL: https://notes-on-enums.contributing-docs.pages.dev

View logs

@github-actions
Copy link

github-actions bot commented Apr 25, 2025

Logo
Checkmarx One – Scan Summary & Details52cb269d-b266-4fa9-add8-fcb049b73df3

New Issues (2)

Checkmarx found the following issues in this Pull Request

Severity Issue Source File / Package Checkmarx Insight
HIGH Cx7c1ed3d7-0e49 Npm-image-size-1.2.0
detailsRecommended version: 1.2.1
Description: Image-size is vulnerable to a Denial of Service (DoS) vulnerability when processing specially crafted images. The issue occurs because of an infine...
Attack Vector: NETWORK
Attack Complexity: LOW

ID: y4BIlV94AVmjXkAZ708ZYCuGNSYDd5ekujUlPJgiLK4%3D
Vulnerable Package
MEDIUM CVE-2025-32014 Npm-estree-util-value-to-estree-3.3.2
detailsRecommended version: 3.3.3
Description: A vulnerability in estree-util-value-to-estree versions prior to 3.3.3 allows an attacker to generate an "ESTree" object that specifies a prototype...
Attack Vector: NETWORK
Attack Complexity: LOW

ID: NEQjYBYhq2k6WHk8zQk%2BC9Eeu0WFk6cZTfHGyfRmi%2BE%3D
Vulnerable Package

@Hinton Hinton self-requested a review April 29, 2025 14:14
Copy link
Member

@Hinton Hinton left a comment

Choose a reason for hiding this comment

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

Some initial thoughts. I'm split on if this belongs in architecture or code style under contribution.

Please review the rendered output https://notes-on-enums.contributing-docs.pages.dev/architecture/clients/enums.

@withinfocus withinfocus changed the title Initial pass of documentation on enums. Initial pass of documentation on enums Apr 29, 2025
@withinfocus
Copy link
Contributor

See comments on bitwarden/clients#14347 too.

I am also of the opinion that this could just end up in code style.

@Patrick-Pimentel-Bitwarden Patrick-Pimentel-Bitwarden requested a review from a team as a code owner May 1, 2025 20:03
Copy link
Member

@eliykat eliykat left a comment

Choose a reason for hiding this comment

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

This reads more like an ADR to me, going into the background for the decision. For Code Style, I think it can be more succinct, e.g. "We don't use Typescript enums because they are not fully typesafe and can cause surprises. Instead of using enums, we use constant objects... [continue with Our Recommended Approach]". I think the links down the bottom are good too. But the intro, reasons, and problems sections are unnecessary imo. Code Style should be short and instructional.

@Patrick-Pimentel-Bitwarden
Copy link
Contributor Author

I abandoned the context and left it with just the recommended approach.

Copy link
Member

@eliykat eliykat left a comment

Choose a reason for hiding this comment

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

My comments have been addressed but I'll let the other reviewers give the final approval once they're happy.

SshKey: 5,
} as const;

export type CipherTypeValue = (typeof CipherTypes)[keyof typeof CipherTypes];
Copy link
Member

Choose a reason for hiding this comment

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

💭 (non-blocking) It would be useful to have a utility type for this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Would you mind providing your justification?

Copy link
Member

@eliykat eliykat May 12, 2025

Choose a reason for hiding this comment

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

Because every time you declare a const object to act as an enum, you're going to need to repeat this code:

export type CipherTypeValue = (typeof CipherTypes)[keyof typeof CipherTypes];

And aside from how much copy/paste that is, I personally can never remember the keyof typeof incantation the first time. It's low level type mapping to have to do every time you declare an enum this way, and the TS syntax is pretty opaque.

Whereas you could do this:

// write this once
export type GetObjectKeys<T> = T[keyof T];

// then when I add an enum, all I need to do is:
// import { GetObjectKeys } ...
export type CipherTypeValue = GetObjectKeys<typeof CipherTypes>;

Copy link
Contributor Author

Choose a reason for hiding this comment

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

okay! I will make this addition in a fast follow to bitwarden/clients#14650 so not to have to re-request reviews and update the docs. Thanks for the callout.


- https://dev.to/ivanzm123/dont-use-enums-in-typescript-they-are-very-dangerous-57bh
- https://www.typescriptlang.org/docs/handbook/enums.html#objects-vs-enums
- https://devblogs.microsoft.com/typescript/announcing-typescript-5-8-beta/#the---erasablesyntaxonly-optio
Copy link
Contributor

@jprusik jprusik May 6, 2025

Choose a reason for hiding this comment

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

typo

Suggested change
- https://devblogs.microsoft.com/typescript/announcing-typescript-5-8-beta/#the---erasablesyntaxonly-optio
- https://devblogs.microsoft.com/typescript/announcing-typescript-5-8-beta/#the---erasablesyntaxonly-option

Copy link
Contributor

Choose a reason for hiding this comment

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

We could potentially drop this link; it's more about options for disabling typescript-specific syntax (of which enums is an example) than reasoning for the adoption of the code style policy 🤷

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed with 69a927a

Comment on lines 9 to 22
export const CipherTypes = {
Login: 1,
SecureNote: 2,
Card: 3,
Identity: 4,
SshKey: 5,
} as const;

export type CipherTypeValue = (typeof CipherTypes)[keyof typeof CipherTypes];

declare function useCipher(type: CipherTypeValue): void;

useCipher(CipherTypes.Login); // ✅ Valid
useCipher(42); // ❌ Invalid
Copy link
Contributor

@jprusik jprusik May 6, 2025

Choose a reason for hiding this comment

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

non-blocking nit:

A different example might be helpful here to avoid conflating the concept of the data model "type" (kind) attribute and the TS type concept

Suggested change
export const CipherTypes = {
Login: 1,
SecureNote: 2,
Card: 3,
Identity: 4,
SshKey: 5,
} as const;
export type CipherTypeValue = (typeof CipherTypes)[keyof typeof CipherTypes];
declare function useCipher(type: CipherTypeValue): void;
useCipher(CipherTypes.Login); // ✅ Valid
useCipher(42); // ❌ Invalid
export const PasskeyActions = {
Register: "register",
Authenticate: "authenticate",
} as const;
export type PasskeyActionValue = (typeof PasskeyActions)[keyof typeof PasskeyActions];
declare function usePasskeyAction(action: PasskeyActionValue): void;
usePasskey(PasskeyActions.Register); // ✅ Valid
usePasskey(42); // ❌ Invalid

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added with 69a927a

@Patrick-Pimentel-Bitwarden Patrick-Pimentel-Bitwarden merged commit 193bc1f into main May 13, 2025
10 checks passed
@Patrick-Pimentel-Bitwarden Patrick-Pimentel-Bitwarden deleted the notes-on-enums branch May 13, 2025 18:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants