Closed littledan closed 4 years ago
Key-value syntax is definitely look like a more future proof solution to me. Also this will make static imports and dynamic imports look more consistent, or are there any other suggestions than import('module', { type: 'json' })
which look more like a single string solution for static imports?
Could the type be treated as the default, but if more parameters need to be defined, switch to k/v syntax? I.e a hybrid approach? The analogy of the default export, which doesn't use braces when importing comes to mind.
Can't there still be key/value syntax with a single string, if encoded as a querystring?
import json from "./foo.json" as "type=json&anotherOption=42";
// and default behavior
import json from "./foo.json" as "json";
// would be equivalent to
import json from "./foo.json" as "type=json";
@Janpot We could do that. My feeling is that more sub-syntaxes will lead to more problems, from a developer experience perspective, from possible diversity/bugs in parsers, etc.
My feeling is that it would leave more freedom to hosts/compilers on how to parse that string. My understanding is that the spec doesn't dictate how the module identifier is interpreted, I feel like in the same way it could leave freedom on how the module attributes are interpreted.
Well, this comes a bit in contrast with the goals articulated in #10
I see. fwiw, I didn't necessarily mean "freedom" as in "no consensus". I meant it more like "allow enough escape hatch for people to come up with ideas that we didn't think of today"
I'd like to call out editor UX here. Key-Value will lead to better completions if we ever have multiple attributes (which I would consider a mandate for this feature personally). Even today I am given sub-par UX with import statements due to their design and would not like to have another UX pitfall here for import
.
@bmeck Are you talking about it being hard to autocomplete the import since you type the module specifier last? As in, it would be more ergonomic to do:
from 'lodash' import { groupBy };
@Janpot that syntax allows tooling to better complete the code as you type, which is my concern yes.
@bmeck I am with you on completions. I think you should usually not have to type the type at all if using editor completions.
Has anybody made a strong argument against supporting both?
import j1 from "./foo.json" as "json";
import j2 from "./foo.json" as {type: "json", bar: "baz"};
const j3 = import("./foo.json", "json");
const j4 = import("./foo.json", {type: "json", bar: "baz"});
The thing I keep coming back to is that nobody can give me a concrete example of what the bar
attribute should be. Of course it makes sense to save those 6 characters if the proposal never grows beyond type:
, but if another attribute comes along and is not only useful but more commonly specified, having a "shorthand version" that's always interpreted as being the type
will seem short-sighted in retrospect. At this point, to me, the opposite seems more likely: that we're currently over-engineering a solution for the general case (bag of key-value attributes) when the immediate need is for a simple case (exactly one attribute).
Well, the basic concern would be that this goes in contrast with goals of minimalism. In the OP, I had some concerns with using as
as a keyword here as well.
@thw0rted I think there are many use case for more than one argument: #22 or https://github.com/littledan/proposal-module-attributes/issues/16#issuecomment-552421527 are one of them in this repo.
I'd like to second the contrast of minimalism.
If you look at things like how default
exports work in JS, they actually add quite a bit of complexity for a programmer to learn even if they are a common usage when importing modules. I find the usefulness of having 2 forms of imports to be plausible, but do not see such currently with module attributes as not all environments are even seeking to use the same attributes for the same purposes/reasoning currently.
I also would prefer minimalism (to me, default as a name is the confusion, not the existence of defaults, but my conclusion here is the same)
After thinking about this a bit more, and chatting with @xtuc @dandclark and @MylesBorins offline, I'm thinking that it might make sense to start with the simple as "string"
form, with a potential follow-on proposal to permit more complex attributes, like as {type: "json", key2: "value2}
.
Advantages:
as
rather than the longer with type:
as
with the flexibility and forward-looking aspects of the key-value syntax, that scales to multiple keys and valuesDisadvantages:
as
looks a bit funny before a complex literal; we may be better off with some other word, if we want to reuse it.@xtuc and @dandclark suggested that for
might be an alternative for as
which makes sense with complex things on either side, but @MylesBorins pointed out that, even reusing as
, the syntax is far from ambiguous: It switches based on whether as
comes before or after the module specifier.
Thoughts?
I thought the committee specifically didn't want to tie this to import types, and wanted to explore generic metadata attached to imports? https://github.com/tc39/notes/blob/master/meetings/2019-12/december-5.md#conclusions
I'm kinda disappointed to see us taking this route, since metadata on types would have been useful. Eg, TypeScript and Flow marked type-only imports, Babel could mark lazy imports, etc.
@jridgewell The proposal leaves non-string metadata open for expansion into objects. In my mind, this is a key requirement, that we're not locking ourselves into just a string. But the idea is to start with a string, and make this further expansion when we are very solid on the use cases for other things (even though we have plenty of ideas).
I've stated in other issues that only tailoring to the web specific type attribute is not appealing. If the intent is not to include the ability to have multiple attributes in this proposal but instead in a follow on proposal I would not be comfortable moving forward.
OK, given the aim of avoiding making the import types special, I'd like to conclude on the general key/value syntax, as is currently in master in this repository. I see this as one of the core questions that we'd be affirming consensus on for Stage 2.
We decided to go with the key-value syntax and reached consensus for stage 2.
Weird it reached consensus.
You have this in readme:
We propose to omit this generalization in the initial proposal, as a key/value list of strings already affords significant flexibility to start, but we're open to a follow-on proposal providing this kind of generalization
So why complicating the syntax, if you're already committed to "omit generalization"? What if it will come out that the type is sufficient, and there wouldn't be follow-on proposal? We will simply end up with weird syntax, having some object-like literal with one usable key: type
.
Imo this code is enough for this particular proposal:
import json from "./foo" as "json";
And if another proposal will come, with support of some useful keys, they will have to bring some "assertions 2.0" with this object-like notation along with it, making key-value notation also available.
I personally think that there's too small chance for more keys to be real useful for assertions, too small to bringing this generalization straight away.
Sorry for notifying a closed thread but I had to say it.
If the JSON module proposal is requiring the host must interpret "type: json" as JSON, it means "type" is special. Maybe we can make as "string literal"
as a shorthand of "type: 'string literal'"
That specialness is a quality of the specification though, not necessarily the runtime - a host might have many assertions available that operate the same way as “type”, and to a user on that host, “type” wouldn’t be special at all.
As a developer, not someone who creates a language, When I see a literal string value I expect it can to be using an expression, is dynamic at runtime or can be taken from a variable. Please do not mix user code with language definition.
That expectation already doesn’t apply to the specifier (the part after the “from”).
True, and I have the same objections about that. Whitespace as separator seems good enough for me.
In the original thread at https://github.com/w3c/webcomponents/issues/839, there are several suggestions of syntax which includes a single string, rather than key-value syntax. Let's discuss the advantages and disadvantages of this option in this thread.
For example, the syntax for an import statement could be:
Advantages of a single string
type:
". Including the type will be annoying enough as is!Advantages of key-value syntax
as
keyword is likely to be pretty confusing, as it's also a keyword with completely different meaning in other parts of an import statementMy opinion is that the advantages of a general key-value syntax outweigh the advantages for a single string. It's circumstantial evidence (since this proposal doesn't suggest acting on any of them yet), but the relatively high number of other possible use cases points to a k/v syntax to me. This would be analogous to the decision to make
import.meta
an object, rather than just adding a syntax forimport.meta.url
.