{"id":19985898,"url":"https://github.com/aeberdinelli/js-guidelines","last_synced_at":"2025-06-19T20:41:21.538Z","repository":{"id":144044985,"uuid":"362695100","full_name":"aeberdinelli/js-guidelines","owner":"aeberdinelli","description":"Documentation about how I believe code should look like, good practice and tips.","archived":false,"fork":false,"pushed_at":"2022-12-03T19:03:24.000Z","size":83,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-10T18:06:35.315Z","etag":null,"topics":["codestyle","es6","eslint","javascript","node"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aeberdinelli.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-04-29T05:00:16.000Z","updated_at":"2022-06-23T14:14:51.000Z","dependencies_parsed_at":"2023-04-22T14:35:01.527Z","dependency_job_id":null,"html_url":"https://github.com/aeberdinelli/js-guidelines","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/aeberdinelli/js-guidelines","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aeberdinelli%2Fjs-guidelines","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aeberdinelli%2Fjs-guidelines/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aeberdinelli%2Fjs-guidelines/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aeberdinelli%2Fjs-guidelines/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aeberdinelli","download_url":"https://codeload.github.com/aeberdinelli/js-guidelines/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aeberdinelli%2Fjs-guidelines/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260827627,"owners_count":23068999,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["codestyle","es6","eslint","javascript","node"],"created_at":"2024-11-13T04:26:44.792Z","updated_at":"2025-06-19T20:41:16.528Z","avatar_url":"https://github.com/aeberdinelli.png","language":null,"readme":"\u003csmall\u003eThis is my set of a few good practice guidelines for JS/TS. In my experience, applying these rules will make the code a lot easier to maintain.\u003c/small\u003e\n\n\u003cdetails\u003e\n   \u003csummary\u003e\n       \u003cstrong\u003eTable of contents\u003c/strong\u003e\n   \u003c/summary\u003e\n   \u003cstrong\u003e{\u003c/strong\u003e\n   \u003cbr\u003e\n    \n   * [General rules](#-general-rules)\n   * [General code style rules](#-general-style-rules)\n   * [Always prefer const](#-always-prefer-const)\n      * [Updating an array](#updating-an-array)\n      * [Updating an object](#updating-an-object)\n   * [Exports](#-exports)\n      * [Export only what you need](#export-only-what-you-need)\n      * [Export named methods](#export-named-methods)\n   * [Arrow functions](#-arrow-functions)\n   * [Null checks](#-null-checks)\n     * [Defaulting a value](#defaulting-a-value)\n     * [Optional property operator](#using-the-new-optional-property-operator)\n   * [Looping through arrays](#-looping-through-arrays)\n     * [Removing items based on condition](#removing-items-based-on-condition)\n     * [Performing operation for each element](#performing-an-operation-for-each-element)\n     * [Customizing elements](#customizing-each-element-of-the-array)\n     * [Using certain items from array](#using-a-certain-item-from-array)\n   * [Spread operator](#-spread-operator)\n   * [Conditions](#-conditions)\n     * [Do not use redundant checks](#do-not-use-redundant-checks)\n     * [Redundant ternary operators](#this-applies-to-ternary-operators-as-well)\n     * [Redundant function returns](#and-in-functions-too)\n     * [Redundant else](#you-dont-need-else)\n   * [Typescript](#-typescript)\n     * [Type everything!](#type-everything)\n     * [Dynamic types](#dynamic-types)\n     * [Keep it simple](#keep-it-simple)\n     * [Avoid duplicated types](#avoid-duplicated-types)\n     * [Monorepos?](#monorepo)\n   \n   \u003cstrong\u003e}\u003c/strong\u003e\n\u003c/details\u003e\n\n# Guidelines for JS {\n\n## \u003ca href=\"https://github.com/aeberdinelli/js-guidelines/blob/master/README.md#readme\"\u003e🠹\u003c/a\u003e General rules\n\u003csmall\u003eThis applies to any language not just JS!\u003c/small\u003e\n- **Avoid using libraries** when possible, especially if you can replicate the methods easily (lodash users I'm talking to you). Reasons? Over-sizing your app, and adding code you don't know.\n- **Always focus on readability** rather than \"looking smart\". Avoid using shorthands or hacks, or using single-character named variables. At the end of the day, the language is not what will make your app slow. If you need to optimize your app, try to optimize images and http requests.\n- **Prevent duplicated code**. You can create any number of reusable functions and it will be far better than re-writing code. Why? If you have to refactor later, you will have to find every copy of the logic while you could just update the function instead.\n- **Keep functions small**. Your function should not work for more than 1 use case. Avoid using a lot of if/else that changes the way it works, create several functions instead. The only place where you could change the implementation based on conditions is within your controllers. In that case, you would call the correct function based on your desired condition. \n\n## \u003ca href=\"https://github.com/aeberdinelli/js-guidelines/blob/master/README.md#readme\"\u003e🠹\u003c/a\u003e General style rules\n- Always use `;` at the end of each line\n- Always include spaces between brackets: `import { Thing, OtherThing } from './stuff';`\n- Always declare arrays in single line when it has only a few elements: `[ 'thing', 'thing2' ];`\n- Keep your code easy to understand, if you're using ternary operators, use it only for one condition - **do not chain them**\n- No matter what kind of indentation you use (spaces/tabs) as long as you use width of 4, this keeps the code clean and very easy to read\n- Use spaces after each parameter in a function or method and between different parts of the declaration: `function something(param1, param2, param3) {`\n- Use spaces to keep conditions and loops easy to read: `if (condition) {` / `for (let i = 0; i \u003c 5; i++) {`\n\n## \u003ca href=\"https://github.com/aeberdinelli/js-guidelines/blob/master/README.md#readme\"\u003e🠹\u003c/a\u003e Always prefer const\nI prefer this for easy debugging and preventing errors. Remember, `const` means you cannot re-assign that variable, but you can change it's value if it is an array or an object.\n\n\u003ch3\u003eUpdating an array\u003c/h3\u003e\n\n```javascript\nconst rows = [];\n\n// This is a React example, but it's valid for other cases too\npeople.forEach(person =\u003e {\n    rows.push(\n        \u003cRow\u003e\n            \u003cCol\u003e{person.name}\u003c/Col\u003e\n        \u003c/Row\u003e\n    );\n});\n```\n\n\u003ch3\u003eUpdating an object\u003c/h3\u003e\n\n```javascript\nconst settings = {};\n\nsettings.darkMode = true;\n```\n\n## \u003ca href=\"https://github.com/aeberdinelli/js-guidelines/blob/master/README.md#readme\"\u003e🠹\u003c/a\u003e Exports\n\u003ch3\u003eExport only what you need\u003c/h3\u003e\n\nIf you have a module with the main method being something like `lowercase`, export only that method.\n\n```javascript\nfunction internal(str) {\n    return str.toLowerCase();\n}\n\nfunction lowercase(str) {\n    return internal(str);\n}\n\n// Do not export everything\nmodule.exports = { internal, lowercase };\n\n// Instead, export the useful methods\nmodule.exports = { lowercase };\n```\n\n\u003ch3\u003eExport named methods\u003c/h3\u003e\nThis also applies to classes. Is better to export a named method instead of a default export. This way, you will force everyone to use your method with the name that you specified and will make maintaince a lot easier, knowing exactly each place the exported method is used. Let me show you an example:\n\n\u003cbr\u003e\n\n```javascript\n// This is a default export\nmodule.exports = function() {}\n\n// This is a named export\nfunction something() {}\n\nmodule.exports = { something };\n\n// Example for default export usage\n// Both will work and they will have different name while they are the same method\nconst something = require('./something');\nconst notSomething = require('./something');\n\n// This will make the method use the same name across your project (unless changing it on purpose)\n// Plus instead of importing the whole module, you just import the method you need\nconst { something } = require('./something');\n```\n\n## \u003ca href=\"https://github.com/aeberdinelli/js-guidelines/blob/master/README.md#readme\"\u003e🠹\u003c/a\u003e Arrow functions?\nI know, arrow functions are sexy. However, they are not always needed. Considerate using them only when:\n\n- You need to maintain context for `this`\n- You only have a single-line logic, like when using `.map()` or `.filter()` \n\nThis will make also the previous rule easier to keep.\n\n## \u003ca href=\"https://github.com/aeberdinelli/js-guidelines/blob/master/README.md#readme\"\u003e🠹\u003c/a\u003e Null checks\nAlways add nullchecks to prevent errors in your console and breaking the flow. \u003cbr /\u003e\nYou can use the falsy check or defaulting some value with the `||` operator. For example:\n\n\u003ch3\u003eDefaulting a value\u003c/h3\u003e\n\n```javascript\nconst name = user.name || 'Unavailable';\n```\n\n\u003ch3\u003eUsing the new optional property operator\u003c/h3\u003e\n\n```javascript\nconst name = user?.details?.name || 'Unavailable';\n```\n\n\u003ch2\u003e\u003ca href=\"https://github.com/aeberdinelli/js-guidelines/blob/master/README.md#readme\"\u003e🠹\u003c/a\u003e Looping through arrays\u003c/h2\u003e\nTry to not use the same iterator method everytime. Instead, use whichever is the better for your case.\n\n\u003ch3\u003eRemoving items based on condition\u003c/h3\u003e\n\n```javascript\nconst adults = people.filter(person =\u003e person.age \u003e= 18);\n```\n\n\u003ch3\u003ePerforming an operation for each element\u003c/h3\u003e\n\nUse `.forEach()` if you don't need to create a new array\n\n```javascript\npeople.forEach(person =\u003e registerPerson(person));\n```\n\n\u003ch3\u003eCustomizing each element of the array\u003c/h3\u003e\n\nIn this case, you can use `.map()` since you need a new array with elements changed\n\n```javascript\n// This way you add new properties to array\nconst people = peopleArray.map(person =\u003e ({\n    ...person,\n    isAdult: (person.age \u003e= 18)\n});\n```\n\n\u003ch3\u003eUsing a certain item from array\u003c/h3\u003e\n\nIf you know what items you have in an array and want to use them, for instance the result of a `.split()` operation, you can do something like this:\n\n```javascript\n// Instead of\nconst parts = fullname.split(' ');\nconst name = parts[0];\nconst lastname = parts[1];\n\n// You can do\nconst [ name, lastname ] = fullname.split(' '); \n```\n\n\n\u003ch2\u003e\u003ca href=\"https://github.com/aeberdinelli/js-guidelines/blob/master/README.md#readme\"\u003e🠹\u003c/a\u003e Spread operator\u003c/h2\u003e\n\nI know sometimes it looks fancy but if you need to grab 8 properties from a 10 properties object, then it's more convenient to just use the object instead of spreading each property from it:\n\n```jsx\n// Instead of doing\nconst { prop1, prop2, prop3, prop4, prop5, prop6, prop7, prop8, prop9, prop10, prop11, prop12 } = obj;\n\n// Refence the object itself\n\u003cp\u003eName: {obj.prop1}\u003c/p\u003e\n\u003cp\u003eLastname: {obj.prop2}\u003c/p\u003e\n```\n\nYour code will look cleaner with a lot less lines while getting the same result.\n\n\u003ch2\u003e\u003ca href=\"https://github.com/aeberdinelli/js-guidelines/blob/master/README.md#readme\"\u003e🠹\u003c/a\u003e Conditions\u003c/h2\u003e\n\n### Do not use redundant checks\nIf you have a condition that always returns either `true` or `false`, you don't need to compare it:\n\n```javascript\n// Do not use\nif (something == true) {\n\n// Instead just do\nif (something) {\n```\n\n### This applies to ternary operators as well\n```javascript\n// Do not use\nresult = (condition != \"\") ? true : false;\n\n// Just do this\nresult = (condition != \"\");\n```\n\n### And in functions too\n\n```javascript\n// Do not do this\nfunction isSomethingTrue(something) {\n    if (something) {\n        return true;\n    } else {\n        return false;\n    }\n}\n\n// Instead do this\nfunction isSomethingTrue(something) {\n    return (something);\n}\n```\n\n### You don't need `else`\nSounds weird, but trust me your code will start to look a lot cleaner and easier to understand. \u003cbr /\u003e\nYou can use `return` or `throw` to stop the flow. \nThere's a good article [right here ↗️](https://medium.com/@jamousgeorges/dont-use-else-66ee163deac3)  if you'd like to read more about this.\n\n```javascript\nfunction getName() {\n    if (!person.name) {\n        return 'Name not available';\n    }\n    \n    return person.name;\n}\n```\n\n\u003ch2\u003e\u003ca href=\"https://github.com/aeberdinelli/js-guidelines/blob/master/README.md#readme\"\u003e🠹\u003c/a\u003e Typescript\u003c/h2\u003e\n\n\"The whole point of using JS is that I don't have to care about types\". I know, most JS developers when first presented TS hate it for this reason. I can assure you, it will help you prevent a lot of common errors. There's no need to use it but if you do, here's some useful tips.\n\n### Type everything!!\nTypes are not only useful to prevent errors and fail compilation if there's a typo somewhere. They're also extremely useful for new developers. You can define the interface of your API (and other things) and welcome new developers to your project.\n\n```typescript\ninterface CreateUserRequest {\n    name: string;\n    lastname: string;\n    age?: number;\n}\n\n// This way people just need to check CreateUserRequest interface to find out what properties you accept\n// Also if the IDE supports it, they will get autocomplete to make the DX delightful.\nexport function CreateUser(body: CreateUserRequest) {\n```\n\n### Keep it simple\nLet's say your app depends on a service that returns a huge object and you only need a few properties. You don't need to type every property in your project, instead, you can use an interface with the properties that you know and use. \n\n### Avoid duplicated types\nYou don't need to rewrite types if you only have to discard one of two properties. Imagine you have a REST API and you have a `product` entity. When you create an object for that entity, you don't know the Id, but when you make a GET request you do. In that case you can do something like this:\n\n```typescript\nexport type Product {\n    name: string;\n    price: number;\n    id: string;\n}\n\n// This is the same as Product, without the id\nexport type ProductCreate = Omit\u003cProduct, 'id'\u003e;\n```\n\n### Dynamic types\nMost TS developers don't take full advantage of the features available. There are a lot of places where `any` should not be an option. Usually they use `any` when they want to reuse a method across different entities. But you don't need to do that!\n\n```typescript\n// ResponseType is dynamic and you can send TS what type you are expecting from the method\nexport function Request(userId: number): Response\u003cResponseType\u003e {\n    return { name: 'Alan' } as ResponseType;\n}\n\n// You use it like this:\ntype User = { name: string };\n\n// response will be of type User and the IDE will get full autocomplete options too\nconst response = Request\u003cUser\u003e(1);\n```\n\n### Monorepo?\nIf you have a React/Node app and a monorepo, you can share your types between both parts of the app. This way, you only have to update the types in one place and is easier to maintain.\n\n# };\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faeberdinelli%2Fjs-guidelines","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faeberdinelli%2Fjs-guidelines","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faeberdinelli%2Fjs-guidelines/lists"}