Skip to content
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

Allow enum variant names that collide with existing types #70

Merged
merged 1 commit into from
Aug 18, 2024

Conversation

jhugman
Copy link
Owner

@jhugman jhugman commented Aug 17, 2024

According to The Big O of Code Reviews, this is a O(n) change.

This small PR tweaks the Variant classes for our typescript version of Tagged Enums, to allow Variants to have names of existing types.

For example, it's not uncommon for Rust programs to have enums constructed like so:

struct Dog {}
struct Cat {}

enum Animal {
  Dog(Dog),
  Cat(Cat),
}

The way we've modeled tagged enums are with a frozen object containing a class for each Variant.

So this would translate to:

type Dog = ; // Dog defined elsewhere
type Cat = ;

const Animal = (() => {
    class Dog {
        constructor(public value: Dog) {
            // This Dog value is the wrong type!
            // value is the type of the Variant class.
        }
    }
    class Cat {
        constructor(public value: Cat) {}
    }
    return Object.freeze({ Dog, Cat });
})();

This commit changes the naming of the Variant class:

type Dog = ; // Dog defined elsewhere
type Cat = ;

const Animal = (() => {
    class Dog_ {
        constructor(public value: Dog) {
            // There is no variant class called Dog yet, just Dog_,
            // so value is the correct type.
        }
    }
    class Cat_ {
        constructor(public value: Cat) {}
    }
    // We rename the Dog_ variant class as Dog here,
    // so the only way to access this class is via Animal.Dog.
    return Object.freeze({ Dog: Dog_, Cat: Cat_ });
})();

This small commit tweaks the Variant classes for our typescript version of Tagged Enums, to allow Variants to have names of existing types.

For example, it's not uncommon for Rust programs to have enums constructed like so:

```rs
struct Dog {}
struct Cat {}

enum Animal {
  Dog(Dog),
  Cat(Cat),
}
```

The way we've modeled tagged enums are with a frozen object containing a class for each Variant.

So this would translate to:

```typescript
type Dog = …; // Dog defined elsewhere
type Cat = …;

const Animal = (() => {
    class Dog {
        constructor(public value: Dog) {
            // This Dog value is the wrong type!
            // value is the type of the Variant class.
        }
    }
    class Cat {
        constructor(public value: Cat) {}
    }
    return Object.freeze({ Dog, Cat });
})();
```

This commit changes the naming of the Variant class:

```typescript
type Dog = …; // Dog defined elsewhere
type Cat = …;

const Animal = (() => {
    class Dog_ {
        constructor(public value: Dog) {
            // There is no variant class called Dog yet, just Dog_,
            // so value is the correct type.
        }
    }
    class Cat_ {
        constructor(public value: Cat) {}
    }
    // We rename the Dog_ variant class as Dog here,
    // so the only way to access this class is via Animal.Dog.
    return Object.freeze({ Dog: Dog_, Cat: Cat_ });
})();
```
Copy link
Collaborator

@zzorba zzorba left a comment

Choose a reason for hiding this comment

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

LGTM

@jhugman jhugman merged commit 5109542 into main Aug 18, 2024
1 check passed
@jhugman jhugman deleted the jhugman/variant-collisions branch August 18, 2024 18:13
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.

2 participants