tc39 / proposals

Tracking ECMAScript Proposals
https://tc39.github.io/process-document/
18.28k stars 717 forks source link

Context-aware imports #541

Open Nefcanto opened 2 hours ago

Nefcanto commented 2 hours ago

Let's imagine a list of posts and a post form. The list has a person filter to show posts of that person only. And a new post has a person field that can be specified as the author of that post.

So, here could be the pseudo-code for the list:

import { Person } from "../person/filter.jsx"

return <List
    filters={<>
        <Person />
    </>}
/>

And the pseudo-code for the form:

import { Person } from "../person/field.jsx"

return <Form
    inputs={<>
        <Person />
    </>}
/>

Now if we move the person's filter and field to its own module, and try to have a barrel file, we encounter a problem.

Two named exports with the same name can not exist in a file

So, our index.jsx file would look like:

import PersonFilter from "../person/filter.jsx"
import PersonField from "../person/field.jsx"

export { PersonFilter }
export { PersonField }

And our pseudo-codes would become:

import { PersonFilter } from "persons"

return <List
    filters={<>
        <PersonFilter />
    </>}
/>

And

import { PersonField } from "persons"

return <Form
    inputs={<>
        <PersonField />
    </>}
/>

While this is still readable, it's less semantically correct. There is no need to suffix the Person component with the word Filter when we are dealing with a list. Also, there is no need to suffix it with the word Field when we are inside a form. A human can understand the context.

I recommend that we add a capability to make imports context-aware. When I say import { Person } from "persons" and I am inside a list file, this should import the filter, and not the field.

How should it know the context? We can have many ways. One that comes to my mind is via configuration. In a config file, we can define contexts and import rules. This could be a pseudo-code in a pseudo-config file:

{
    "contexts": [
        {
            "name": "list",
            "files": ".*list.jsx",
            "rules": {
                "postFixImportIfNotFound": "Filter"
            }
        },
        {
            "name": "form",
            "files": ".*form.jsx",
            "rules": {
                "postFixImportIfNotFound": "Field"
            }
        }
    ]
}

For large systems, this helps code semantics a lot. An enterprise software easily has more than 500 lists and forms. This improvement can help code become more readable. The aforementioned pseudo-code would become:

import { Person } from "persons"

return <List
    filters={<>
        <Person />
    </>}
/>

And

import { Person } from "persons"

return <Form
    inputs={<>
        <Person />
    </>}
/>
six-ponies commented 2 hours ago

  您好,您的邮件已收到,我将尽快给您回复。谢谢

bzk1994 commented 2 hours ago

你好,来信已收到

wmertens commented 2 hours ago

One thing I love about JavaScript is that it's explicit. There is little magic and a new developer doesn't need to know much about a project before being able to participate.

However this proposal, they have to first read the config and remember it while reading project code.

It becomes harder to reason about code, which is not a good thing IMHO.