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

Add getKnownPropertyNames #111

Merged
merged 4 commits into from
Jul 13, 2023
Merged

Add getKnownPropertyNames #111

merged 4 commits into from
Jul 13, 2023

Conversation

mcmire
Copy link
Contributor

@mcmire mcmire commented Jun 29, 2023

This function has been copied from various projects, where it is common to transform an enum into another data structure. For instance:

enum InfuraNetworkType {
  mainnet = 'mainnet',
  goerli = 'goerli',
  sepolia = 'sepolia',
}

const infuraNetworkClientConfigurations =
  Object.keys(InfuraNetworkType).map((network) => {
    const networkClientId = buildInfuraNetworkClientId(network);
    const networkClientConfiguration = {
      type: NetworkClientType.Infura,
      network,
      infuraProjectId: this.#infuraProjectId,
    };
    return [networkClientId, networkClientConfiguration];
  });

As the above example shows, one could use Object.keys() or even Object.getOwnPropertyNames() to obtain said properties. A problem occurs, however, if the type of the properties of the resulting object needs to match the type of the properties in the enum, that means the variable inside the loop needs to be of that type, too. Both Object.keys() and Object.getOwnPropertyNames() are intentionally generic: they returns the property names of an object, but neither can make guarantees about the contents of that object, so the type of the property names is merely string[]. While this is technically accurate, we don't have to be so cautious in these situations, because we own the object in question and therefore know exactly which properties it has.

This commit adds a getKnownPropertyNames function which is like Object.getOwnPropertyNames() except that the resulting array of property names will be typed using the types of the properties of the given object. In the above example that would mean that the type of network would be a type union of the keys of InfuraNetworkType and not string.

This function has been copied from various projects, where it is common
to transform an enum into another data structure. For instance:

```
enum InfuraNetworkType {
  mainnet = 'mainnet',
  goerli = 'goerli',
  sepolia = 'sepolia',
}

const infuraNetworkClientConfigurations =
  Object.keys(InfuraNetworkType).map((network) => {
    const networkClientId = buildInfuraNetworkClientId(network);
    const networkClientConfiguration = {
      type: NetworkClientType.Infura,
      network,
      infuraProjectId: this.#infuraProjectId,
    };
    return [networkClientId, networkClientConfiguration];
  });
```

As the above example, one could use `Object.keys()` or even
`Object.getOwnPropertyNames()` to obtain said properties. A problem
occurs, however, if the type of the properties of the resulting object
needs to match the type of the properties in the enum, that means the
variable inside the loop needs to be of that type, too. Both
`Object.keys()` and `Object.getOwnPropertyNames()` are intentionally
generic: they returns the property names of an object, but neither can
make guarantees about the contents of that object, so the type of the
property names is merely `string[]`. While this is technically accurate,
we don't have to be so cautious in these situations, because we own
the object in question and therefore know exactly which properties it
has.

This commit adds a `getKnownPropertyNames` function which is like
`Object.getOwnPropertyNames()` except that the resulting array of
property names will be typed using the types of the properties of the
given object. In the above example that would mean that `network` would
have a type of `InfuraNetworkType` and not `string`.
src/misc.ts Outdated Show resolved Hide resolved
Copy link
Member

@Gudahtt Gudahtt left a comment

Choose a reason for hiding this comment

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

LGTM!

@mcmire mcmire merged commit a1e5d90 into main Jul 13, 2023
@mcmire mcmire deleted the add-get-known-property-names branch July 13, 2023 16:54
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.

3 participants