This is the error message that I am getting on Visual Studio Code.
[ts] File is a CommonJS module; it may be converted to an ES6 module.
[ts] Unexpected token. A constructor, method, accessor, or property was expected.
[eslint] Parsing error: Unexpected token .
module export= (property) export=: {
[x: string]: any;
Snippet: typeof Snippet; }
This is for a class called Snippet [Some of you might find this a little bit long but I was advised to show what is inside Snippet - fyi]:
class Snippet {
/**
* #constructor
* #param {any} fileName - file name.
* #param {any} code - code.
* #param {any} numTags - number of tags.
* #param {any} tags - all tags.
*/
constructor(fileName, code, ...tags) {
this.name = fileName;
this.code = code;
this.tags = tags;
this.lines = code.split(/\r\n|\r|\n/).length;
}
/**
* #function
* #name myFunction
* #param {any} tag - check tag.
* #return {boolean} boolean
*/
hasTag(tagCheck) {
if (this.tags.hasOwnProperty(tagCheck)) {
if (Object.prototype.hasOwnProperty.call(this.tags, tagCheck)) {
return true;
}
else {
return false;
}
}
}
}
I have tried these 4:
module.exports = {
Snippet:Snippet
};
module.exports = {
Snippet
};
module.exports = {
Snippet:Snippet,
};
module.exports = {
Snippet,
};
I am still getting the same error message that I have quoted.
Does anyone know how to fix this problem?
Thank you in advance, really appreciate it.
Related
I'm trying to use tsc with plain, Vanilla JS and I'm stumped on how to declare the type a function.
It seems like it should be this simple:
/** #type PersonGreet */
person.greet = function greet(other) {
return `Hello ${other.name}, my name is ${person.name}!`;
};
Edit: /** #type PersonGreet */ is correct. The current behavior is a bug in tsc. The selected answer below gives valid workarounds.
Reduced Test Case
Ignore the fact that someone may want to refactor this into using classes or prototypes or some such - it serves well as a demonstration of the problem.
Repo: https://github.com/BeyondCodeBootcamp/hello-tsc
"use strict";
/**
* #typedef {Object} Person
* #property {String} name
* #property {PersonGreet} greet
*/
/**
* #typedef {Function} PersonGreet
* #param {Person} other
* #returns {String}
*/
let Person = {};
/**
* Creates a person
* #param {Object} p
* #param {String} p.name
* #returns {Person}
*/
Person.create = function (p) {
let person = {};
person.name = p.name;
/////////////////////////////////////////////////////////////////////////////////
//
// error TS7006: Parameter 'other' implicitly has an 'any' type. <======= WRONG!
//
/////////////////////////////////////////////////////////////////////////////////
/** #type PersonGreet */
person.greet = function greet(other) {
return `Hello ${other.name}, my name is ${person.name}!`;
};
return person;
};
module.exports = Person;
Incorrectly Typed as "any"
When I run tsc to check it gives an error about an implicit any:
tsc -p jsconfig.json
person.js:28:33 - error TS7006: Parameter 'other' implicitly has an 'any' type.
28 person.greet = function greet(other) {
~~~~~
Found 1 error in person.js:28
What to do?
To me this seems like a bug in tsc... but this is JS 101 stuff, surely there must be a way to type a function?
What annotation do I need to use to declare the function's type? Or can tsc / tsserver / typescript just not handle this kind of rudimentary use of JS?
Solution 1
You should use #callback instead of #function like so:
"use strict";
/**
* #typedef {Object} Person
* #property {String} name
* #property {PersonGreet} greet
*/
/**
* #callback PersonGreet
* #param {Person} other
* #returns {String}
*/
let Person = {};
/**
* Creates a person
* #param {Object} p
* #param {String} p.name
* #returns {Person}
*/
Person.create = function (p) {
let person = {};
person.name = p.name;
/** #type {PersonGreet} */
person.greet = function greet(other) {
return `Hello ${other.name}, my name is ${person.name}!`;
};
return person;
};
module.exports = Person;
Solution 2
Or, declare a #typedef using typescript syntax like the following:
/**
* #typedef {(other: Person) => string} PersonGreet
*/
When I declare a class with ctor, and then use this class only as a function's input parameter, I get no-unused-vars from eslint.
Code:
/**
* A class
*/
class SampleClass{
/**
* Ctor
* #param {string} par - a parameter
*/
constructor(par) {
this.par = par;
}
}
/**
* Func
* #param {SampleClass} param - a sample class
* #returns {SampleClass} - the same class
*/
function fName(param) {
return param;
}
So as you can see, I use SampleClass both as input parameter and as return type of the function, but eslint shows error: 'A class "SampleClass" is defined but never used. eslint no-unused-vars'
How can i fix this? Of course, I need to leave this type of check workong.
I couldn't fully understand what you wanted to do with that function and class, but within my understanding, I think this would work
class SampleClass {
constructor(par){
this.par = par;
}
getInstance() {
return this.par
}
}
function fName(params) {
return params
}
const newClass = new SampleClass("param");
fName(newClass.getInstance())
I found that I need to use a cleverer eslint parser - #babel/eslintparser. It does not raise this error when I use classes.
I have a module that is going to be exported to npm to be used in other projects and for others that could use it to enjoy the library as well.
The code works, if you know the methods and properties you can call them and they work.
However (in my case) Intellisense isn't picking them up whereas other npm modules do (i.e. ws)
I published the module/library to npm and installed it into my new project (https://i.imgur.com/mU7hA2H.png for reference on the intellisense I am seeing)
Now my question is as follows, am I missing a step in order to get this to work so that developers see the available methods and properties?
I've tried looking into other modules and see how they did it, but from what I can tell this should show up in intellisense, but it doesn't...
'use strict';
class ParkDS {
constructor() {
var c = require('./Config/Config');
var d = require('./DataSource/DataSource'));
this.config = new c();
this.datasource = new d();
this.certificate = {
Cert: "",
Key: ""
};
}
/**
* #returns {Object}
* #public
* */
get Config() {
return this.config;
}
/**
* #returns {Object}
* #public
* */
get DataSource() {
return this.datasource
}
/**
* #returns {Object}
* #public
* */
get Certificate() {
return this.certificate;
}
/**
* #public
* */
Test() {
console.log("test");
}
/**
* #public
* */
Start() {
// Code to start all services
}
/**
* #public
* */
Stop() {
// Code to stop all services
}
}
module.exports = ParkDS;
I expect the intellisense to show Config, DataSource, and Cerfificate as Properties, and Test, Start, Stop as Methods
I have a CONST object that holds all my constants.
To set a constant, I have a function setConst(), that adds a new key to the CONST object, if it doesn't exist.
However, Webstorm can't track these variables. I'm trying to resolve it, by using jsDoc, but can't seem to find the right code. Here is what I have tried:
/**
* #name MY_CONST
* #param CONST.MY_CONST
* #type {String}
* #memberOf CONST
*/
setConst('MY_CONST', 'hello');
//Using MY_CONST here throws an Unresolved Variable in Webstorm
MyFunction.prototype[CONST.MY_CONST] = function() {...}
function setConst(key, value) {
if(CONST[key]) {
throw "Key " + key + " already exists in CONST";
}
CONST[key] = value;
}
Can you fix this with jsDoc? Or do I just have to accept the unresolved variable errors?
Found the right jsDoc combination - here it is:
/**
* #prop CONST.MY_CONST
* #type {String}
* #memberOf CONST
*/
I am trying to understand the JSDoc style for documenting JavaScript that is used with the JavaScript Closure Compiler. I have the JavaScript code below
// ==ClosureCompiler==
// #compilation_level ADVANCED_OPTIMIZATIONS
// ==/ClosureCompiler==
(function(){
/**
* #type Array.<string>
* #private
*/
var sb = [];
/**
* #const
* #type{{append: function(string): SingletonStringBuffer, toString: function(): string}}
*/
window['SingletonStringBuffer'] = {
/**
* #param {string} text
* #return {SingletonStringBuffer}
*/
append: function(text){
sb.push(text);
return SingletonStringBuffer;
},
/**
* #return {string}
*/
toString: function(){
return sb.join("");
}
};
}());
When I do an advanced compile on this code I am receiving 2 warnings.
JSC_TYPE_PARSE_ERROR: Bad type annotation. Unknown type SingletonStringBuffer at line 10 character 35
* #type{{append: function(string): SingletonStringBuffer, toString: function()...
^ JSC_TYPE_PARSE_ERROR: Bad type annotation. Unknown type SingletonStringBuffer at line 15 character 11
* #return {SingletonStringBuffer}
^
The function append returns a deference to the encapsulating object. The variable that it is returning ,SingletonStringBuffer, is declared... so I am not sure what is wrong or how to correct it.
You haven't created a named type as far as the compiler is concerned. For this case, I would expect you to create an interface:
/** #interface */
function StringBuffer() {
}
/**
* #param {string} text
* #return {StringBuffer}
*/
StringBuffer.prototype.append;
etc
This can be declared either in the code (if you are using advanced mode it will be stripped) or in your extern files (if you want the type without the code in simple mode).
You can then use it like so (in your case):
(function(){
/**
* #type Array.<string>
* #private
*/
var sb = [];
/**
* #const
* #type {StringBuffer}
*/
window['SingltonStringBuffer'] = {
/**
* #param {string} text
* #return {StringBuffer}
*/
append: function(text){
sb.push(text);
return SingltonStringBuffer;
},
/**
* #return {string}
*/
toString: function(){
return sb.join("");
}
};
}());
singletons work differently in closure. I have not seen an explicit annotation for it, but the compiler (in advanced mode) has some understanding of certain built-in functions
Singletons would be declared via the goog.addSingletonGetter function, here is a code sample
/**
* #constructor
* #extends {path.to.BaseClass}
*/
path.to.MyClass = function() {
goog.base(this);
};
goog.inherits(path.to.MyClass, path.to.BaseClass);
goog.addSingletonGetter(path.to.MyClass);
and that be it.
PS
you are getting the bad annotation because {SingltonStringBuffer} is never declared as a class.
PPS.
Some rambling on post the fact.
I suspect (but this is untested) that making the constructer private might work. Notice the trailing underscore in the example
/**
* #private -> NOTE THIS IS IN NO WAY VERIFIED
* #constructor
* #extends {path.to.BaseClass}
*/
path.to.MyClass_ = function() {
goog.base(this);
};
goog.inherits(path.to.MyClass, path.to.BaseClass);
goog.addSingletonGetter(path.to.MyClass);