When I add a function to the Math object, it does not show inside IntelliSense of VSCode.
Math.dot = function (a,b) {};
If you don't have one already, create a type declaration module file (Ex. index.d.ts) in the root of your project folder, and add to it the following:
declare interface Math {
doc: (a:number, b:number) => number;
}
You can read more about type declaration module files in the official docs at https://www.typescriptlang.org/docs/handbook/declaration-files/templates/module-d-ts.html.
In simpler cases, you can just use JS Doc comments, since a basic subset of JS Doc comments are supported by VS Code's intellisense facilities. As far as I know, this is not one of those supported cases (declaring the type of a function on an existing global object).
Related
I use VS Code for JavaScript.
Definitions within a file work sometimes, but not others. Does anyone know why they fail?
In this example, VS Code finds the definition for edit easily. There is no occurrence of the word 'something' anywhere else in this file. Completely unique. So, why can't VS Code find its definition?
If I knew why, maybe I could change my code to work around it.
VS Code also can't find any references to these 'lost' properties. Which is very frustrating for tracking down where a function is called etc.
You should use this.
const edit = {
something: 5,
test() {
this.something;
},
};
You must not use an arrow function for test field, or this would point elsewhere but not the edit object.
EDIT: In TypeScript 4.3.5, the latest version of TS at the time of writing, TS is able to detect self-references in object literals, and both edit.something and this.something would work. For the case of working with JavaScript, upgrading VS Code should do the trick.
A TS playground link for reference.
There is a length limit. IntelliSense will define type :any if an object description is too long.
There is no way around this at all. The :any type will overwrite imported type definitions (e.g., a .d.ts file).
Two solutions:
Don't write long object declarations in your code.
Don't use VS Code or IntelliSense.
As for specifics:
The behavior is unpredictable.
If a type definition does not generate, reducing the object description length will not cause it to generate
Reducing an object description length to below the limit and re-launching VS Code will cause it to re-generate.
The length limit is unpredictable.
A function definition is 'longer' than a string, even if they have the same character count.
A nested ('deep') object declaration is longer than a shallow ('flat') object declaration, even if they have the same character count.
In short: IntelliSense breaks irreparably if you try to write long object declarations in a JS file.
TypeScript compiles to JavaScript stripping nearly all of the TypeScript syntax and identifiers from the resulting JavaScript code. If given piece of TypeScript syntax is not a valid JavaScript code then you won't see a trace of it in the compiled output.
One exception that I know of is enum.
TypeScript code (invalid in JS)
enum Alph {
a, b, c = "www"
}
actually shows in compiled JavaScript output as
var Alph;
(function (Alph) {
Alph[Alph["a"] = 0] = "a";
Alph[Alph["b"] = 1] = "b";
Alph["c"] = "www";
})(Alph || (Alph = {}));
Question
What TypeScript syntax constructs, other than enum, that are not JS constructs, compile to some JavaScript code and not just disappear? I'm especially interested in constructs that expose TypeScript identifiers in JS, like enum does.
Clarification
Here's an example of what I have in mind when I say about TypeScript specific constructs and identifiers 'disappearing' from the output.
TypeScript
interface Inter {
a: number;
}
class C implements Inter {
a: number = 1;
}
var b: number = 1;
JavaScript compiler output
class C {
constructor() {
this.a = 1;
}
}
var b = 1;
You can see that there's no trace of interface, implement, Inter or number. But the variable declaration and assignment is unchanged and class is passed to JS barely changed.
Default value was moved to the constructor so properties default values might be a minor example of what I'm looking for. Constructs that can't be just copied or removed but have to undergo some transformation to make sense in JS.
"What are TS constructs other than enum that have to be transformed into something at runtime?"
The short answer is all of them, it's just a matter of how much. Keep in mind that Typescript is both a type system and a compiler. You code is being reconstructed into an abstract source tree, then re-emitted according the the logic of the compiler. So everything is always getting transformed, it's just that most of the time the output and the original code are pretty similar.
So I'm going to answer a more defined question that I think you're asking:
What Typescript keywords do not exist in JS, yet emit JS code when compiled.
There are a few things (like private instance variables #foo, decorators #f(), or JSX). These are items that are in proposal stages of JS but not yet widely adopted, or are defined by other standards or transpilers, that have become first class citizen within the language of typescript. For those cases typescript outputs an equivalent implementation that should work in all modern JS interpreters that generates a lot of code the programmer isn't meant to utilize directly.
But I'm assuming you don't care about those cases too much either since the generated code could be removed if all interpreters supported these constructs the same way.
So that leaves:
enum
namespace (Though I think usage of namespace is discouraged for new typescript code these days, and the supporting code is pretty minimal)
And yeah. Pretty sure that's all of them.
Taking a brief look of electron-react-boilerplate repository in github I realized a code in javascript that couldn't understand.
declare module "flow-bin" {
declare module.exports: string;
}
What it does declare?, it's part of ES6, ES7? I've searching in the way though can't find something about it. Anyone can give me some information about what it mean?
That is typescript's grammar. Use to
ambient module declaration
Typescript use declare to do a strict type checking.Then make a grammar check before compile.For eg.
declare var jQuery: (string) => any;
jQuery('#foo');
The above code declare that the jQuery accept a string parameter.
Kotlin enables the extension of existing types. For example we can do this:
fun String.replaceSpaces(): String {
return this.replace(' ', '_')
}
val formatted = str.replaceSpaces()
However in JavaScript this is an antipattern.
Does Kotlin sidestep the issues that this causes in Javascript?
No this is not an antipattern. In js its an antipattern because js is dynamic and therefore changing a prototype changes how code works at runtime making it an antipattern. This is also extremely dangerous based on how the in operator works and based on the fact that you can rewrite everything, so changing a prototype can affect code somewhere on your page:
Number.prototype.toString = function(){
return "bullshit";
};
alert(""+12);
In kotlin this is not the case as kotlin is static, and all references are built at compile time. Additionally, you cant overwrite existing methods so its not dangerous at all.
You cannot compare a prototyped language like JS with Kotlin. All extensions are resolved statically and do not modify the extended type ("receiver"). This is really important and invalidates your worry. Please have a look at the documentation to learn more about the things happening with extensions in the background (compiler).
In my opinion, you need to be cautious with extensions though. Don't allow each and every developer in a Kotlin project to add new extensions to random types. I think the project must define certain rules handling the process of defining new functions/properties on existing types, because otherwise it can get hard to read foreign code. Also there should be firm arranged locations where to put those extensions.
No it is not good. It is very bad that Kotlin allows extensions of existing types.
With extensions there is no reason at all to create a class hierarchy or even create a new class definition for that matter.
Kotlin creators might as well have just used erlang instead of going to the trouble of creating extensions.
Extensions mean that you can no longer rely on a class definition to be constant. Imagine all the time people are going to spend just finding a developer's "creative" extensions let alone debugging them.
You should have compiled this example and seen the generated code. Everything would become clear:
function replaceSpaces($receiver) {
return replace($receiver, 32, 95);
}
function foo(str) {
var formatted = replaceSpaces(str);
}
There's no monkey patching at all! Extension functions are just a syntactic sugar in Kotlin. It's just another way of passing first argument to a static function.
Several languages had this already. The problem with JavaScript is the way it works, as stated in the answer of the link.
JavaScript has a couple way of overriding property. A library could have very well defined a override, but the other one override it again. The function get called from both library, all hell breaks loose.
It’s more a type system and visibility issue in my opinion.
The main arguments against extending prototypes in JavaScript are twofold:
The methods you add might have the same name as methods added by some library used in the same application, but have different behaviour.
Future version of JavaScript/ECMAScript itself might include a method with the same name as the one you're adding, but with different behaviour.
In JavaScript, both of these scenarios will lead to the wrong version of a method being called at runtime, unexpectedly, resulting in a runtime crash or unexpected runtime behaviour.
In Kotlin, most scenarios akin to this will result in a compile-time error or at least a warning, and so the perils encountered when extending types in JavaScript are mostly avoided in Kotlin. However, there is still some slight scope to encounter similar runtime bugs in rare cases.
To illustrate this, let's write some examples of code where conflicting implementations of a method exist, and see what happens.
Scenario 1: Two libraries provide an extension method with the same signature
Suppose we have this code, in Main.kt and Library1.kt respectively:
import library1.*
import library2.*
fun main() {
listOf(99, 101, 103, 104).printOddVals()
}
package library1
fun List<Int>.printOddVals() {
for (x in this) {
if (x % 2 != 0) {
println(x)
}
}
}
So the library1 package defines a printOddVals method that prints the odd values in a list, and main() uses it. Now suppose that in library2, we introduce a conflicting printOddVals method, that prints the values with odd indices:
package library2
fun List<Int>.printOddVals() {
for ((i, x) in this.withIndex()) {
if (i % 2 != 0) {
println(x)
}
}
}
In the equivalent scenario in JavaScript, this would probably cause a runtime bug. In Kotlin, it merely leads to a compile-time error:
Main.kt:5:31: error: overload resolution ambiguity:
public fun List<Int>.printOddVals(): Unit defined in library1 in file Library1.kt
public fun List<Int>.printOddVals(): Unit defined in library2 in file Library2.kt
listOf(99, 101, 103, 104).printOddVals()
^
IntelliJ IDEA will also tell you how to fix the issue - by introducing an import alias:
Do that, and we get this code, with the ambiguity about which printOddVals we want to call resolved:
import library1.*
import library2.*
import library2.printOddVals as printOddVals1
fun main() {
listOf(99, 101, 103, 104).printOddVals1()
}
Scenario 2: A library introduces a member function that shadows an extension method you already wrote
Suppose we have the following files:
package library1
class Cow {
fun chewCud() {}
}
import library1.*
fun Cow.moo() {
println("MOOOOOOO!")
}
fun main() {
val cow = Cow()
cow.moo()
}
So Cow.moo is initially an extension method we wrote. But then we update library1, and then new version has a moo member function:
package library1
class Cow {
fun chewCud() {}
fun moo() { println("moo") }
}
Now, because member functions are preferred to extension functions when resolving method calls, our extension function is not used when we call cow.moo() in main(), and then library's new member function is used instead. This is a change in runtime behaviour, and potentially a bug if the library's new moo() implementation isn't an adequate substitute for the extension function we'd written before. However, the saving grace is that this at least produces a compiler warning:
Main.kt:3:9: warning: extension is shadowed by a member: public final fun moo(): Unit
fun Cow.moo() {
^
Scenario 3: A library introduces a member function that shadows an extension method you already wrote, and doesn't produce a compiler warning
Once we add inheritance (or interface implementation) into the mix, we can contrive a situation similar to the one above where an extension function we were previously using gets partially shadowed by a member function after a library update, causing changes in runtime behaviour, and no compiler warning occurs.
This time, suppose we have these files:
import library1.*
fun Animal.talk() {
println("Hello there! I am a " + this::class.simpleName)
}
fun main() {
val cow = Cow()
val sheep = Sheep()
cow.talk()
sheep.talk()
}
package library1
interface Animal
class Cow : Animal
class Sheep : Animal
At first, when we run our main() function, our extension function gets used for both cow.talk() and sheep.talk():
Why hello there. I am a Cow.
Why hello there. I am a Sheep.
. But suppose we add a talk member to Cow:
package library1
interface Animal
class Cow : Animal {
fun talk() {
println("moo")
}
}
class Sheep : Animal
Now if we run our program, the member function on Cow gets preferred to the extension method, and our program's behaviour has been changed - all with no compiler errors or warnings:
moo
Why hello there. I am a Sheep.
So although extension functions are mostly safe in Kotlin, there's still a tiny bit of potential to run into the same pitfalls as in JavaScript.
Is this theoretical danger sufficient to mean that extensions should be used sparingly, or perhaps avoided entirely? Not according to the official Coding Conventions, which take the view that extensions are great and you should use them lots:
Extension functions
Use extension functions liberally. Every time you have a function that works primarily on an object, consider making it an extension function accepting that object as a receiver. To minimize API pollution, restrict the visibility of extension functions as much as it makes sense. As necessary, use local extension functions, member extension functions, or top-level extension functions with private visibility.
You are, of course, free to form your own view!
I'm looking for something that will import the contents of an object to the global scope:
var y = {}
y.x = 5
//do some magic here
console.log(x); //5
I want to do this is so I can make an easy to use module with memorable function names without having to worry about things accidentally getting overridden by other modules.
Consider this example:
funModule = {};
funModule.washClothes = function(clothes){...}
funModule.walkDog = function(dogName){...}
//etc
funModule.UNITED_STATES_DEFICIT = ...;
Here I've created a module that has some useful functions and constants (implementations and values were replaced with "...").
I don't want my users to have to type out the module name every time they call function or use a constant. That would result with really messy code:
funModule.walkDog(funModule.UNITED_STATES_DEFICIT);
I could try it again by defining everything globally:
washClothes = function(clothes){...}
walkDog = function(dogName){...}
//etc
UNITED_STATES_DEFICIT = ...;
but if a different module has also defined the commonly named function washClothes we've got trouble. (in my actual case the commonly named function is run)
Removed from technical context, here is the problem I'm faced with:
Firstly I want to use simple and memorable names to make the module easy to learn and fun to use.
Secondly I don't want the easy names to make the module impossible to use with others. Especially as it grows, a lot of common names will be used. It would be great if the users could decide whether or not import the names directly.
Thirdly I realized as I'm typing this that what I'm describing is something that definitely already exists, in python. See http://effbot.org/zone/import-confusion.htm for more detail.
tl;dr How can python-like imports be done with javascript?
EDIT:
It seems there is not a universal way to do this.
Using Window won't work in all environments (but will work in any common browser).
Apparently ES6 Modules are not available to web browsers directly.
This question is different from this one because its not about Node.js. I was looking for a universal way to do it, but that doesn't seem possible, so I'll limit it to web browsers, (namely chrome, firefox, safari, opera, and maybe ie)
EDIT:
This general article about Scope could be useful for anyone with a similar question as mine: https://toddmotto.com/everything-you-wanted-to-know-about-javascript-scope/
Object.prototype.makeglobal=function(){
for(key in this){
if(window[key]){//replace window if youre not in a browser
//already exist, error handling
console.error(key+' already exist in window');
}else{
window[key]=this[key];
}}};
Use like this:
funModule.makeglobal();
//now you can
washClothes();
But this is bad as it pollutes the global object.
2.Your user should create his own namespace:
function(){
this.washClothes();
//more of his content
}.call(funModule);
3.You could also add a loader:
funModule.load=function(func){
console.log(func);
console.log(this);
func.call(this,this);
};
Now you can do:
funModule.load(function(fun){
this.washClothes();
fun.washClothes();
});
4.If youre concerned about readability you may use function chaining (?):
funModule.washClothes=function(){
//your code
return this;
}
now you can do:
funModule.washClothes("tshirts").washClothes("trousers").washClothes();
ES6 Modules are what you want.
If you will define your object as es6 module you could do this (using the names in your example):
import { washClothes } from "fun-module";
and then washClothes will be globally available on the file that imported it, just like you want.
Read about it here.
If you really want a magic solution like in the comment in your post and don't want to use ES6 and you run in the browser you can put it on the window object:
window.x = 5
In JavaScript, at least in a browser, global variables are properties of the window object: that is, window.x and x (where x is global) reference the same value. So, in theory, you could use Object.assign() to copy your object's properties to the window object making them global variables. This is roughly equivalent to globals().update(myobj.__dict__) in Python.
But just as import * is usually a bad idea in Python, so too this sounds like a bad idea, except even worse because window has a lot of other properties that you probably don't want to clobber.
After some additional research I found a way, without polluting the global namespace, to allow users to directly access module contents.
This solution allows the user to:
Write code that directly references the module's functions/properties
Define precedence if there are multiple modules written in this same style
Still access the module's functions/properties by module name*
*This feature comes with a catch
Here's the code
Module
funModule = {};
//This stuff is the arbitrary contents of the module:
funModule.washClothes = function(clothes){...}
funModule.walkDog = function(dogName){...}
//etc
funModule.UNITED_STATES_DEFICIT = ...;
//etc
//This part is necessary:
funModule.run(userApp)
{
for(key in this){
eval(key + " = " + this[key] + ";");
}
userApp();
}
The only way (that I could find) to dynamically define functions both in funModule.run's scope and in funModule is to use Eval. Using call, apply, or bind to manipulate scope would still require use of the this keyword and the whole point of this unusual style is to make client code as simple and non-repetitive as possible.
Client Code 1
function myApp()
{
washClothes(UNITED_STATES_DEFICIT);
}
funModule.run(myApp);
Here in the client code it is possible to directly access everything except for funModule.run. So the global namespace is kept clean but the user's code does not need unnecessary repetition.
Client Code 2
function myApp()
{
washClothes(UNITED_STATES_DEFICIT);
}
funModule.run( otherModule.run.bind({},myApp) ); //otherModule has precedence here
Assume otherModule is a different module that features the same run function. funModule will load its contents then call its first argument. The first argument will load otherModule's contents, overriding anything from funModule with the same name.
Client Code 3
function myApp()
{
//directly access stuff from funModule
walkDog()
var big = UNITED_STATES_DEFICIT * 3.14;
//explicitly access stuff from specific modules
clothes = new otherModule.Clothes();
funModule.washClothes(otherModule.washClothes(clothes));
}
funModule.run(myApp)
This is the feature that makes use of eval necessary. The user can opt out of ambiguity of direct access. They can still access properties/methods by naming the module they come from.
But Why?
Some StackOverflow users were understandably concerned about the unusual set of constraints in the question, so I figured I would answer the following question:
Why don't you use a short alias for your module.
I tried to answer that question in this article, which pulls from this question and answer.