I am using TypeScript to generate some DOM element from a templated string. Now I know that in plain old javascript + JQuery you can do: var domObj = $(myString) or to make it more evident: var comObj = $('<div></div>'); and it works just like that.
I've been trying to do the same with TS and I always get some error telling me it can't say which overload to use.
Is there any other way to do what I'm trying to do?
Can it be done in TS?
Edit:
The issue I'm facing is not how to use JQuery from TypeScript is about a specific feature I want to load a string variable to a JQuery object, I know it can be done in plain old js but I get overloading errors when doing so.
Unlike this question which asks how to use JQuery from ts, which I have mostly figured out except for that little details I have just mentioned
Based on my comment above, you need to use a type assertion in order to avoid that error.
The most versatile option would be to use the any type since that will prevent typing errors from being thrown:
var comObj = ($('<div></div>') as any);
// or
var comObj = (<any>$('<div></div>'));
// or
var comObj: any = $('<div></div>');
Without seeing the full code, it's hard to know what exactly was happening in your case.
However, without context, it seems like the problem is that the compiler thinks that you are passing a string that represents a CSS selector, but in reality you were passing in stringified HTML, which results in the error that you are seeing.
As a side note, here is a relevant snippet in the TypeScript documentation under advanced intersection types. As you can see, the variable result is essentially coerced using the <any> type assertion:
let result = <T & U>{};
for (let id in first) {
(<any>result)[id] = (<any>first)[id];
}
Related
I'm trying to read a JSON array. Every time i try to read the array/value by passing JSON object key like this-
json[key]
It shows a Eslint error-
[eslint] Generic Object Injection Sink (security/detect-object-injection)
I understand its a security warning because the key may not exists. But how do i resolve this warning? Is there any easier way to read the Json object. My plan is to pass the "key" to the function and read the json based on the key.
You are searching for an ES lint error fix:
Here is the syntax for it
json [`${key}`]
Example:
const obj = {
eventName: 'Music event',
landingPic: 'landing.jpg',
eventPic0: 'pic0.jpg',
eventPic1: 'pic1.jpg',
eventPic2: 'pic2.jpg',
eventPic3: 'pic3.jpg',
artist: 'Elie'
};
// array of keys which need to be read
const arrayOfKey = ['landingPic', 'eventPic0', 'eventPic1', 'eventPic2', 'eventPic3'];
// let's read the value by a key in array
arrayOfKey.forEach( key => {
const value = obj[`${key}`];
console.log(value);
});
There is a good answer here. In general this rule is for paranoiac and the article to which everyone appeal is a mislead. So the best answer, I would say is to turn this rule off, if you can for sure.
And another answer in the comments refers to eslint contributor answer that this rule is pretty false positive prone and more for human to audit a codebase(warning level) rather then give an error in a CI. So I would say you can totally ignore this rule or turn it off.
If you cannot turn it off or ignore, you can disable the eslint for line with comment that it's a false positive or use some interpolation as mentioned in other answers.
And finally, in order to destroy any doubts, the answer from creator of the rule:
"I'm the original author of this rule - for a bit of context, it was originally written as an assistive tool for manual code reviews, to be
used with the eslint plugin for VS Code. I would recommend disabling
it for other use cases, as it's just going to be far too noisy."
Unsure why, but typecasting the access parameter silences the error. Guessing this has something to do with sanitation being able to prevent pollution.
const myThing = myObj[String(key)]
const myThing = myObj[key as string]
What its trying to say is that using this notation:
You are able to modify even prototype properties of the object which is considered dangerous
By being able to modify everything, you are also able to modify the constructor (method/function) so it may be injected and then exploited.
The subject is described analytically here, providing a simple example:
https://web.archive.org/web/20150430062816/https://blog.liftsecurity.io/2015/01/15/the-dangers-of-square-bracket-notation
I'm learning Javascript and I wrote the following code:
if (mystring.len > 0) {
// do stuff
}
I accidentally used .len instead of .length. To my surprise, no error was raised. mystring.len returned undefined and this made the comparison fail but the code kept right on running. I would prefer an actual error to be raised so I can fix the code. Adding "use strict" didn't help, nor did jslint.
I know there are ways to actively check whether or not a property exists, but that's not what I'm looking for. I want Javascript to tell me when I've made a typo in a property name.
Is there a way to cause Javascript to give an error in this case?
Nope - that is how JavaScript works and it's incredibly useful. Who is to say that checking len is something that needs fixing? Consider:
if(mystring.len === undefined) {
mystring.len = "Test";
}
The best you can do is to simply check that the thing is defined before using it:
if(mystring.len !== undefined) {
}
I appreciate the strangeness, and how it doesn't feel robust (having originally come from a C# background) but there isn't a lot you can do unfortunately. The fact that JavaScript is case sensitive makes this even more frustrating. You will learn to live with it though!
If you really really wanted to run some static analysis then you could considering creating a transpiler (e.g. Babel) extension to run this sort of analysis - but it would get really difficult if you ever expected something to be undefined which I find is common place.
edit
Here's a real example that I'd use where undefined is useful. I'm working with a library that needs to move stuff from one location to another. It can't do that unless the original location has been specified, so I might write something like the following, initializing values if I don't have them for some reason:
function update(node) {
if(node.x === undefined) { node.x = 0; }
node.y = node.y || 0; // This is the shorthand way I'd actually write it
// Do some other stuff
};
"use strict" (in my experience) is used so that variables that aren't explicitly declared/instantiated that are then referenced will throw errors (else, JS would just make a new var on the fly). So that wouldn't help here.
This sounds like an error that would typically be picked up by a compiler in other languages, but since JS is interpreted, you won't have that kind of explicit error checking unless you're in a beefy IDE. Are you using a text editor or something to write JS?
Thats not the way JavaScript considers your above code. Every variable in JS is an object. So, when you do mystring.len, its actually trying to access the len property of mystring obj and when it doesn't find that property, it will return undefined - which is how it should be. Thats why you will not be able to find any error using JSLint.
Just to give you an example -
var myObj = {name: 'Hello', id: 1};
console.log(myObj.name); // Returns 'Hello'
console.log(myObj.text); // 'undefined'
In order to prevent such code from giving you any errors, you can easily use the hasOwnProperty() method like follows-
if(myObj.hasOwnProperty('text')) doSomething();
Since myObj doesn't have any property text, the doSomething() function will never be called.
This is the behaviour of JavaScript as mentioned by many/all answers. However there is an option to prevent new properties you might want to try:
Object.seal https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/seal
The simple answer is JavaScript is not ment to be typesafe...You shouldn't check it, but if you still want to check you can do it by:
if ('len' in mystring){
}
You should look into Typescript if you ask this question...
Sometimes I need enum-like structures for fixed sets of string valus in Node.JS. Basically an object with keys for each enum value, and each value is a string equal to the key:
var State = {FOO: 'FOO', BAR: 'BAR', SOME_REALLY_LONG_NAME: 'SOME_REALLY_LONG_NAME'};
This enables me to type State.S and the IDE will suggest State.SOME_REALLY_LONG_NAME, and typos are practically eliminated. I can do if (x === State.FOO) etc.
The above syntax is however obviously not ideal due to the duplication of each literal during creation of the set of values. So I can do for example:
var State = _.indexBy(['FOO', 'BAR', 'SOME_REALLY_LONG_NAME'];
However, as soon as the object is created indirectly, the IDE (WebStorm in my case) will be unable to suggest/auto-complete the values. Sure, with JavaScript we're not very spoiled with working auto-complete anyway, but in my case it bugs me because the whole purpose of my "enum" is to simplify usage of a fixed set of strings.
There are also several enum utilities to create more proper enums, but they will suffer from the same thing. Also, if what I need is basically a fixed set of strings, more proper enums would force me into writing State.FOO.key to get the string value.
Is there a clever way to accomplish these really simple {key: 'key'} mappings without having to type each key twice during creation, but while still maintaining the IDE's understanding of which properties exist in the object? I'm guessing WebStorm only performs a static code analysis which goes out the window as soon as a function is called? Or is there some clever trick?
It's been a while that i used Webstorm, and it's macro-utilities, but maybe u can write a simple macro that expands your String-Array into the desired Structure.
Otherwise, you could try the Typescript-plugin. First of All: every valid JS should be valid TS (don't know exactly about ES7, and if some of the ES6 may bug the plugin).
But TS has a Enum-implementation and webstorm should therefore give you autocompletition and type-safety
I'm trying (perhaps in vain) to come up with a way to use the publish-subscribe pattern while a) using no libraries and b) minimizing boilerplate code in modules that use it. So far the best I've come up with is this:
var handle = document.createElement();
var unsubscribe = AwesomeModule.subscribe(handle);
handle.addEventListener('awesome', function() {
console.log('awesome');
});
This will work pretty well, except that people using AwesomeModule might be confused by having to provide a random DOM element that isn't used as an element.
I tried the following and it doesn't work too well:
var handle = Object.create(EventTarget);
var unsubscribe = AwesomeModule.subscribe(handle);
handle.addEventListener('awesome', function(){
console.log('awesome')
});
I get TypeError: Object [object Object] has no method 'addEventListener'. Interestingly enough, it doesn't seem to look in the prototype chain even though handle has EventTarget as its prototype.
Why doesn't this work? Is there a way implement EventTarget with pure JS? Can it be done in a single line of code that won't horrify users of AwesomeModule?
EDIT: I don't know why it didn't occur to me last night, but I suppose EventTarget being an interface means that it doesn't have implemented code. What's confusing is that in the Chrome debugger console Object.create(EventTarget) makes an object that appears to have addEventListener in is prototype chain. Maybe its lying. Can anyone explain this behavior? Can anyone explain why W3 chose not to make EventTarget a concrete "class"?
It looks like the answer to my original question is "yes." Since JavaScript doesn't have an inheritance model like Java which does compile-time checks for legal implementation, I suppose any Object can implement an interface merely by having methods with the same name. However, doing this would constitute making a library since the addEventListener code isn't implemented in EventTarget (I had previously assumed it was). Since there seems to be no cross-browser way to get a vanilla EventTarget, I will probably use window.addEventListener in conjunction with custom events.
The source is located here: https://code.google.com/p/chromium/codesearch#chromium/src/third_party/trace-viewer/src/base/event_target.js&sq=package:chromium&type=cs&l=18
If you can't modify it, you can always replicate it.
Here's a simple set of routines that works well.
with a small polyfill for IE9 and 10, support is decent.
you can incorporate these functions into your project as needed, i don't think it constitutes a library, or i wouldn't post this.
var on = addEventListener.bind(window),
off = removeEventListener.bind(window),
emit = function(name, val) {
dispatchEvent(new CustomEvent(name, {
detail: val
}));
};
// demo:
on("test", function(e){ alert(e.detail);});
emit("test", "Number is " + Math.random());
i don't think it can get much simpler (~180 chars) without sacrificing speed or library compatibility.
Edit: I found this interesting library which looks like it can do exactly what I was describing at the bottom: https://github.com/philbooth/check-types.js
Looks like you can do it by calling check.quacksLike.
I'm fairly new to using javascript and I'm loving the amount of power it offers, but sometimes it is too flexible for my sanity to handle. I would like an easy way to enforce that some argument honors a specific interface.
Here's a simple example method that highlights my problem:
var execute = function(args)
{
executor.execute(args);
}
Let's say that the executor expects args to have a property called cmd. If it is not defined, an error might be caught at another level when the program tries to reference cmd but it is undefined. Such an error would be more annoying to debug than explicitly enforcing cmd's existence in this method. The executor might even expect that args has a function called getExecutionContext() which gets passed around a bit. I could imagine much more complex scenarios where debugging would quickly become a nightmare of tracing through function calls to see where an argument was first passed in.
Neither do I want to do something on the lines of:
var execute = function(args)
{
if(args.cmd === undefined || args.getExecutionContext === undefined ||
typeof args.getExecutionContext !== 'function')
throw new Error("args not setup correctly");
executor.execute(args);
}
This would entail a significant amount of maintenance for every function that has arguments, especially for complex arguments. I would much rather be able to specify an interface and somehow enforce a contract that tells javascript that I expect input matching this interface.
Maybe something like:
var baseCommand =
{
cmd: '',
getExecutionContext: function(){}
};
var execute = function(args)
{
enforce(args, baseCommand); //throws an error if args does not honor
//baseCommand's properties
executor.execute(args);
}
I could then reuse these interfaces amongst my different functions and define objects that extend them to be passed into my functions without worrying about misspelling property names or passing in the wrong argument. Any ideas on how to implement this, or where I could utilize an existing implementation?
I don't see any other way to enforce this. It's one of the side effects of the dynamic nature of JavaScript. It's essentially a free-for-all, and with that freedom comes responsibility :-)
If you're in need of type checking you could have a look at typescript (it's not JavaScript) or google's closure compiler (javascript with comments).
Closure compiler uses comments to figure out what type is expected when you compile it. Looks like a lot of trouble but can be helpful in big projects.
There are other benefits that come with closure compiler as you will be forced to produce comments that are used in an IDE like netbeans, it minifies your code, removes unused code and flattens namespaces. So code organized in namespaces like myApp.myModule.myObject.myFunction will be flattened to minimize object look up.
Cons are that you need to use externs when you use libraries that are not compiler compatible like jQuery.
The way that this kind of thing is typically dealt with in javascript is to use defaults. Most of the time you simply want to provide a guarentee that certain members exist to prevent things like reference errors, but I think that you could use the principal to get what you want.
By using something like jQuery's extend method, we can guarentee that a parameter implements a set of defined defaults.
var defaults = {
prop1: 'exists',
prop2: function() { return 'foo'; }
};
function someCall(args) {
var options = $.extend({}, defaults, args);
// Do work with options... It is now guarentee'd to have members prop1 and prop2, defined by the caller if they exist, using defaults if not.
}
If you really want to throw errors at run time if a specific member wasn't provided, you could perhaps define a function that throws an error, and include it in your defaults. Thus, if a member was provided by the caller, it would overwrite the default, but if it was missed, it could either take on some default functionality or throw an error as you wish.