News for hackers. Stuff that matters.
Re:Best practices for TypeScript monorepo by madeofpalk on Thursday August 25, 2022 @02:23PM (#32597855)
> Use Absolute Paths for Importing Code Blocks

    import { FormType } from '../../../../types/form';
    import { DateType }   from '../../../../types/date';
    
    // This is considered bad practice
Disagree on this one. Beauty of typescript is giving you auto-import autocompletion in your editor, and not having to worry about relative paths any more. I don't think I've manually written an import statement in years.
Re:Best practices for TypeScript monorepo by 015a on Thursday August 25, 2022 @05:58PM (#32600458)
All code is fast to write. Decisions like this should be optimized for reading and comprehension, not writing.

IMO: Extreme opinions one way or the other don't work, and thus (most of the time) code-complete automation also doesn't work.

    import { User } from "./User"; # is probably the most readable and comprehensible way to write this.
    import { User } from "app/domain/users/types/User"; # is probably less comprehensible
    import { User } from "../User"; # may be ok, but it may also depend on how deep this directory is, because
    import { User } from "app/users"; # is actually pretty comprehensible
The point should be to make it really quick for readers to understand where this code is coming from. Imagine a situation where you've got identically named imports; like a

    import { User } from "foo/db/types"; # used to schematize a user in the database
    import { User } from "foo/api/createUser/types"; # used to schematize a component of the request body for creating users
Maybe the tokens themselves are named poorly, but look past that.

Many people find a specific file using, simply, CMD+P (or your editor's equivalent). There's no context for where they may be at; which inherently makes relative imports less comprehensible.

    import { User } from "./User";
    const u = new User(req.body.user); # but wait... what kind of user did I just create?
There are many ways to help alleviate this low state of comprehension; and what should be deployed is difficult to create hard-and-fast rules around because its so domain specific.

    import { User } from "foo/api/createUser/types"; 
    # having an import path like this can help, but maybe only in small files where the imports aren't 500 lines above where they're used.

    import { User as CreateUserAPIUser } from "./User"; 
    # aliasing imports is a good solution 
    
    import * as createUserApiTypes from "foo/api/createUser/types";
    const u = new createUserApiTypes.User(req.body.user); 
    # importing, then properly naming, the entire module is in my experience an underutilized tool to help with comprehension.
Re:Best practices for TypeScript monorepo by lelandfe on Thursday August 25, 2022 @10:33PM (#32602723)
> what kind of user did I just create?

Do y’all look at the import path at the top of a file to understand a function on line 450?

Any editor I can think of provides a way to show what you’re using here. I don’t think import path intelligibility should really be that high on the list of concerns.

> (most of the time) code-complete automation also doesn't work

They’re pretty great these days, in my experience.

Re:Best practices for TypeScript monorepo by 015a on Friday August 26, 2022 @01:32AM (#32603693)
> Do y’all look at the import path at the top of a file to understand a function on line 450?

It depends on the language, the editor, and the development process. There's no one-size-fits-all solution.

Regardless of all of that: code files are near their peak productivity when they can fit on-screen without scrolling, and when you can put all that aside and just immediately move your eyes from the token to the import path. And they're even closer to the peak when you can combine that with encoded contextual information about the import path (which is generally a reflection of what the token does) into the token itself; via, say, import aliasing or importing the module and accessing the token as a property on that imported module.

The reality that we have thousand-line source files obviously isn't ideal. No one who has ever worked with one would say "this is the way the world should be". But, they exist, and thus we have tools like Intellisense to make them manageable, and they'd definitely be less comprehensible without those tools. That doesn't make the whole situation ideal, when talking in hypotheticals. We shouldn't admit defeat to the God of Complexity by saying, even in this small corner of good practices, "well, the comprehensibility of the import path doesn't matter because we gave up on making anything comprehensible a long time ago."

> They’re pretty great these days, in my experience.

I don't mean that they don't work in the sense that they don't produce compileable import paths. Though this is true in some languages, or some projects with bespoke configuration systems, or in some editors.

I mean that they don't work because they don't oftentimes produce comprehensible import paths.

Re:Best practices for TypeScript monorepo by lelandfe on Friday August 26, 2022 @08:27AM (#32606487)
> The reality that we have thousand-line source files obviously isn't ideal

Cut that number by 2/3 and the situation is the same, right? How often are you working on files where the entirety of them fit on screen at all times…

> well, the comprehensibility of the import path doesn't matter because we gave up on making anything comprehensible a long time ago

I think they don’t matter because even modest complexity produces this situation. This isn’t a hypothetical, it’s the far reaching majority of real, practical code.

Re:Best practices for TypeScript monorepo by bsimpson on Thursday August 25, 2022 @05:44PM (#32600316)
Using relative imports that ../ out of your package directory confuses TypeScript about which files are in-scope (and how to structure the resulting files). You can end up with weird shit like my-library/dist/my-library/index.js. (I'm sure you can configure your way out of this. That's a puzzle I haven't solved and don't intend to invest time into.)

Yarn Berry has a node_modules mode now, which makes it behave like Yarn Classic and NPM. It also allows you to import sibling projects in a monorepo:

    "peerDependencies": {
      "my-library": "workspace:*",
which means you can

    import { thing } from 'my-library'
and have it work as expected, even when my-library is a sibling project in your monorepo.
Re:Best practices for TypeScript monorepo by Jochim on Thursday August 25, 2022 @03:43PM (#32598999)
Personally I'm a fan of using relative paths for anything in the same directory or a sub-directory of the current file and absolute paths for everything else.

I feel like it keeps things clean while also providing a way to distinguish between closely related modules and imports from further away in your application.

Re:Best practices for TypeScript monorepo by throwaway284534 on Thursday August 25, 2022 @06:13PM (#32600598)
I’ve also fallen back into favoring relative paths and doing my best to keep nested paths to a minimum. This also makes publishing on Deno’s module listing possible too!
Re:Best practices for TypeScript monorepo by latchkey on Thursday August 25, 2022 @03:34PM (#32598863)
I think this can be generalized into "use the method that works best with automated tooling".
Re:Best practices for TypeScript monorepo by madeofpalk on Thursday August 25, 2022 @03:52PM (#32599124)
I think that's very fair, and great advice. We have a strong preference against eslint rules that don't have an auto-fix option.
Re:Best practices for TypeScript monorepo by optiomal_isgood on Friday August 26, 2022 @08:04AM (#32606262)
If TypeScript and VSCode are configured properly, it will suggest an auto-import that uses the absolute paths. In my experience, it can be a bit inconsistent though and sometimes it goes for the relative paths instead.