|
| 1 | +--- |
| 2 | +title: Enums |
| 3 | +description: Learn how to easily define, use, and manage constant values using this epic feature called "enums" that TypeScript brings to the table. |
| 4 | +menuWeight: 7.4 |
| 5 | +paths: |
| 6 | + - switching-to-typescript/enums |
| 7 | +--- |
| 8 | + |
| 9 | +# [](#enums) Enums! |
| 10 | + |
| 11 | +Enums are an awesome feature offered by TypeScript that can be used to create automatically enumerated global constant identifiers that can also be used as custom types. We've dedicated an entire lesson to enums because they're a new feature brought into JavaScript by TypeScript, and because they can be massively useful in certain projects. |
| 12 | + |
| 13 | +## [](#lets-talk-about-constants) Let's talk about constants |
| 14 | + |
| 15 | +If you've followed along with any of the more advanced courses in the Apify academy, or at least read the [Best practices]({{@link web_scraping_for_beginners/best_practices.md}}) lesson in the **Web scraping for beginners** course, you'll definitely be familiar with the idea of constant variables. In a nutshell, we create constant variables for values that will never change, and will likely used in multiple places. The naming convention for constants is **ALL_CAPS_AND_UNDERSCORED**. |
| 16 | + |
| 17 | +Here's an object of constant values that we've prepared for use within our project. |
| 18 | + |
| 19 | +```TypeScript |
| 20 | +const fileExtensions = { |
| 21 | + JAVASCRIPT: '.js', |
| 22 | + TYPESCRIPT: '.ts', |
| 23 | + RUST: '.rs', |
| 24 | + PYTHON: '.py', |
| 25 | +}; |
| 26 | +``` |
| 27 | + |
| 28 | +No problem, this will totally work; however, the issue is that TypeScript doesn't know what these values are, but it infers them to just be strings. We can solve this by adding a type annotation with a custom type definition: |
| 29 | + |
| 30 | +```TypeScript |
| 31 | +// DON'T DO THIS! Use enums instead! |
| 32 | + |
| 33 | +// Since TypeScript infers these values to be just strings, |
| 34 | +// we have to create a type definition telling it that these |
| 35 | +// properties hold super specific strings. |
| 36 | +const fileExtensions: { |
| 37 | + JAVASCRIPT: '.js'; |
| 38 | + TYPESCRIPT: '.ts'; |
| 39 | + RUST: '.rs'; |
| 40 | + PYTHON: '.py'; |
| 41 | +// Define the object's values |
| 42 | +} = { |
| 43 | + JAVASCRIPT: '.js', |
| 44 | + TYPESCRIPT: '.ts', |
| 45 | + RUST: '.rs', |
| 46 | + PYTHON: '.py', |
| 47 | +}; |
| 48 | +``` |
| 49 | + |
| 50 | +> Using an actual concrete value such as `'.js'` or `24` or something else instead of a type name is called a [literal type](https://www.typescriptlang.org/docs/handbook/literal-types.html). |
| 51 | +
|
| 52 | +And now we'll create a variable with a hacky custom type that points to the values in the `fileExtensions` object: |
| 53 | + |
| 54 | + |
| 55 | + |
| 56 | +Because of the custom type definition for `fileExtensions` and the type annotation used for the `values` variable, we are getting some autofill for the variable, and the variable can only be set to values within the `fileExtensions` object. Though this implementation might be useful somewhere, it kind of sucks for a few reasons. We had to write our `fileExtensions` property twice (once for TypeScript, and another time to actually initialize the object), and had to use a weird type definition for `values`. |
| 57 | + |
| 58 | +Don't worry, there's a better way! Enter **enums**. |
| 59 | + |
| 60 | +## [](#creating-enums) Creating enums |
| 61 | + |
| 62 | +The [`enum`](https://www.typescriptlang.org/docs/handbook/enums.html) keyword is a new keyword brought to us by TypeScript that allows us the same functionality we implemented in the above section, plus more. To create one, simply use the keyword followed by the name you'd like to use (the naming convention is generally **CapitalizeEachFirstLetterAndSingular**). |
| 63 | + |
| 64 | +```TypeScript |
| 65 | +enum FileExtension { |
| 66 | + // Use an "=" sign instead of a ":" |
| 67 | + JAVASCRIPT = '.js', |
| 68 | + TYPESCRIPT = '.ts', |
| 69 | + RUST = '.rs', |
| 70 | + PYTHON = '.py', |
| 71 | +} |
| 72 | +``` |
| 73 | + |
| 74 | +## [](#using-enums) Using enums |
| 75 | + |
| 76 | +Using enums is straightforward. Simply use dot notation as you normally would with a regular object. |
| 77 | + |
| 78 | +```TypeScript |
| 79 | +enum FileExtension { |
| 80 | + JAVASCRIPT = '.js', |
| 81 | + TYPESCRIPT = '.ts', |
| 82 | + RUST = '.rs', |
| 83 | + PYTHON = '.py', |
| 84 | +} |
| 85 | + |
| 86 | +const value = FileExtension.JAVASCRIPT; |
| 87 | + |
| 88 | +console.log(value) // => ".js" |
| 89 | +``` |
| 90 | + |
| 91 | +## [](#using-enums-as-types) Using enums as types |
| 92 | + |
| 93 | +The nice thing about enums is that they can be used directly in type annotations as somewhat of a custom type. Observe this function: |
| 94 | + |
| 95 | +```TypeScript |
| 96 | +const createFileName = (name: string, extension: string) => { |
| 97 | + return name + extension; |
| 98 | +}; |
| 99 | +``` |
| 100 | + |
| 101 | +We can restrict `extension` so that it can only be a value in the enum by replacing `extension: string` with `extension: FileExtension`: |
| 102 | + |
| 103 | +```Typescript |
| 104 | +enum FileExtension { |
| 105 | + JAVASCRIPT = '.js', |
| 106 | + TYPESCRIPT = '.ts', |
| 107 | + RUST = '.rs', |
| 108 | + PYTHON = '.py', |
| 109 | +} |
| 110 | + |
| 111 | +const createFileName = (name: string, extension: FileExtension) => { |
| 112 | + return name + extension; |
| 113 | +}; |
| 114 | + |
| 115 | +// Call the function and use the enum to populate the second parameter |
| 116 | +const fileName = createFileName('hello', FileExtension.TYPESCRIPT); |
| 117 | + |
| 118 | +console.log(fileName); |
| 119 | +``` |
| 120 | + |
| 121 | +We don't get autocomplete, but the `extension` parameter is now restricted to the values defined in the `FileExtension` enum. |
| 122 | + |
| 123 | +## [](#next) Next up |
| 124 | + |
| 125 | +The `enum` keyword is just the tip of the iceberg of the exclusive features TypeScript has to offer. Let's now [learn about]({{@link switching_to_typescript/type_aliases.md}}) type aliases (custom types!) with the `type` keyword. |
0 commit comments