You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently type annotation is only allowed in TypeScript file. Although we do allow .d.ts files to be consumed by JavaScript files, there are already code bases employing JsDoc @typedef tag to define types within JavaScript files (Google Closure, etc). Supporting @typedef tag will enhance the editing experience for Salsa on these existing code bases.
The purpose of @typedef is to define a new type that can be used in other JsDoc comment annotations, similar to interface or type alias declaration in TypeScript. However, because there is no definite standard on the shape of @typedef, its has several popular dialects. The most common cases I found are as follows:
Case 1:
/** * @typedef {(string | number)} NumberLike */
Case 2:
/** * @typedef {Object} People * @property {number} id the unique id * @property {string} name - your name */
Case 3:
/** * @typedef People * @type {Object} * @property {number} id the unique id * @property {string} name - your name */
There are several difficulties / design choices for the current TypeScript type system to understand the above cases:
Does the code need to be valid JavaScript code if ignoring the comments?
For example:
/**@typedef {string}*/StringType;
is totally fine with the Google Closure compiler, while running the code directly will generate errors because the variable StringType is not defined.
How does these types translate to TypeScript types?
In simple cases, the @typedef functions similarly to type alias in TypeScript. However, the type name defined by @typedef can be a dotted name (as shown in case 6), while in TypeScript type alias name has to be an identifier. And like in case 6, a defined type (People) may be augmented later (added People.person property), which is hard to do for a type alias.
The other route is to represent all the types as interfaces. This solves some of the the augmentation issue, because interfaces can have multiple declarations and be merged together, however it has flaws too. For example:
in which the union type is hard to represent using interfaces.
For case 4 or case 5, do we create both a value declaration and a type declaration for the variable? Imagine the following code:
/**@typedef {(string | number)} */varfoo;
...
varfoo=10;// <- What is "foo" after this line? Should we give you an error / warning?if(foo){// If I call "Go to declaration" on "foo", where will I go to?
...
}
In addition, if the variable only has a type declaration, potentially naming conflicts could happen. For exapmle, the following TypeScript code wouldn't have any error:
Types defined by @typedef should have a scope, and it may or may not be related to their parent node (they may not even have a parent node). For example:
Both TypeA and TypeB should live inside the block scope that function A contains.
Feedback is welcome to these questions, as I am not a heavy JsDoc user, so I might have missed some scenarios. I will keep prototyping potential solutions and update with a proposal once a reasonable design was reached.
The text was updated successfully, but these errors were encountered:
Can you give context for what some of these actually mean? For instance, I am not sure what the specific differences are between 4 and 5, and I'm not sure whether they're defining a type or declaring the type of a variable. Can you also clarify the difference between @type and @typedef?
However, the type name defined by @typedef can be a dotted name
Technically this could synthesize a namespace for the left portion of the qualified name.
I would assume that @typedef maps to a type alias declaration. that applies to scoping rules, and merging. TypeScript allows for a name (Symbol) to have multiple meanings (value, type or namespace), so your var foo example, foo is both a typename, and a variable name. the compile will use its type in type position and use its value in value position. goto declaration will take you to both places.
the syntax of @typedef is not something we can control however, so i would check JS code in github, and see what is the most common patterns and support these.
the namespace.type should be possible as well, we just have to create a namespace symbol for namespace and attach the type type alias declaration to it.
@DanielRosenwasser@typedef is used to define a type, while @type is used to describe the type of the next declaration. For example:
/**@typedef {(string | number) NumberLike*/
defines a union type called NumberLike. This declaration can be written in the other popular format as (with or without the var, basically that's also the only difference between case 4 and case 5 above):
/**@typedef {(string | number)*/varNumberLike;
These translate to TS code:
typeNumberLike=string|number;
And later in other JsDoc comments, you can say
/**@type {NumberLike}*/varfoo;
@mhegazy after browsing how people use @typedef on github I found that case 6 is pretty popular. So if we represent the types using type aliases, does that mean:
Currently type annotation is only allowed in TypeScript file. Although we do allow
.d.ts
files to be consumed by JavaScript files, there are already code bases employing JsDoc@typedef
tag to define types within JavaScript files (Google Closure, etc). Supporting@typedef
tag will enhance the editing experience for Salsa on these existing code bases.The purpose of
@typedef
is to define a new type that can be used in other JsDoc comment annotations, similar to interface or type alias declaration in TypeScript. However, because there is no definite standard on the shape of@typedef
, its has several popular dialects. The most common cases I found are as follows:Case 1:
Case 2:
Case 3:
Case 4:
Case 5:
Case 6:
There are several difficulties / design choices for the current TypeScript type system to understand the above cases:
Does the code need to be valid JavaScript code if ignoring the comments?
For example:
is totally fine with the Google Closure compiler, while running the code directly will generate errors because the variable
StringType
is not defined.How does these types translate to TypeScript types?
In simple cases, the
@typedef
functions similarly to type alias in TypeScript. However, the type name defined by@typedef
can be a dotted name (as shown in case 6), while in TypeScript type alias name has to be an identifier. And like in case 6, a defined type (People
) may be augmented later (addedPeople.person
property), which is hard to do for a type alias.The other route is to represent all the types as interfaces. This solves some of the the augmentation issue, because interfaces can have multiple declarations and be merged together, however it has flaws too. For example:
in which the union type is hard to represent using interfaces.
For case 4 or case 5, do we create both a value declaration and a type declaration for the variable? Imagine the following code:
In addition, if the variable only has a type declaration, potentially naming conflicts could happen. For exapmle, the following TypeScript code wouldn't have any error:
However, we are reporting syntax errors for the corresponding JavaScript code using
@typedef
:Types defined by
@typedef
should have a scope, and it may or may not be related to their parent node (they may not even have a parent node). For example:Both
TypeA
andTypeB
should live inside the block scope that functionA
contains.Feedback is welcome to these questions, as I am not a heavy JsDoc user, so I might have missed some scenarios. I will keep prototyping potential solutions and update with a proposal once a reasonable design was reached.
The text was updated successfully, but these errors were encountered: