streaming-video-technology-alliance / common-media-library

A common library for media playback in JavaScript
Other
43 stars 2 forks source link

Replace Typescript enums with constants #103

Closed littlespex closed 2 weeks ago

littlespex commented 1 month ago

Typescript enums produce non-optimal code when compiled:

enum CmcdStreamingFormat {
    DASH = 'd',
    HLS = 'h',
    SMOOTH = 's',
    OTHER = 'o',
}
var CmcdStreamingFormat;
(function (CmcdStreamingFormat) {
    CmcdStreamingFormat["DASH"] = "d";
    CmcdStreamingFormat["HLS"] = "h";
    CmcdStreamingFormat["SMOOTH"] = "s";
    CmcdStreamingFormat["OTHER"] = "o";
})(CmcdStreamingFormat || (CmcdStreamingFormat = {}));

There is another way to express constrained sets using as const which produces more concise output, though it's more verbose to author:

const CmcdStreamingFormat = {
    DASH: 'd',
    HLS: 'h',
    SMOOTH: 's',
    OTHER: 'o',
} as const;

export type CmcdStreamingFormat = typeof CmcdStreamingFormat[keyof typeof CmcdStreamingFormat];
const CmcdStreamingFormat = {
    DASH: 'd',
    HLS: 'h',
    SMOOTH: 's',
    OTHER: 'o',
};

It would help reduce the code size of production apps using CML if we used the const style. Also of note, this would not constitute a breaking change, and would be transparent to users of CML. The only downside would be that APIs docs might not be as clean.

littlespex commented 1 month ago

@cjpillsbury Anything to add on this topic? Do you have any experience documenting the as const style?

cjpillsbury commented 1 month ago

Here are a few callouts:

  1. Discussion from TS folks - https://www.typescriptlang.org/docs/handbook/enums.html#objects-vs-enums (some pitfalls for Enums usage are also discussed on this page)
  2. Using type structures + data structures can still handle enum benefits in your type relationships pretty easily with a few handy conventions. Below are some examples:

Derive and exporting the const "lookup object"/"map"'s type

export const CmcdStreamingFormat = {
    DASH: 'd',
    HLS: 'h',
    SMOOTH: 's',
    OTHER: 'o',
};

export type CmcdStreamingFormat = typeof CmcdStreamingFormat;

Get the value types to use as a type elsewhere

type ValueOf<T> = T[keyof T];
// Or whatever naming convention you prefer here
type CmcdStreamingFormats = ValueOf<CmcdStreamingFormat>;

const someFn = (streamingFormat: CmcdStreamingFormats) => {
  // do stuff;
};