Can someone explain why the following typescript code compiles? It seems to me that it could never successfully run.
class Xyz
{
static x : Abc = new Abc();
}
class Abc
{
}
There is no compile-time error, since it is equivalent to this syntactically valid JavaScript
var Xyz = (function () {
function Xyz() {
}
Xyz.x = new Abc();
return Xyz;
})();
var Abc = (function () {
function Abc() {
}
return Abc;
})();
but it will have a runtime error since you try to instantiate a member of Abc before Abc is defined.
TypeScript doesn't do any enforcement of ordering of constructs in your code. Consider some slight variant that would be valid -- it's not immediately obvious what things should be allowed or disallowed in terms of ordering.
class Xyz
{
static x = () => new Abc();
}
class Abc
{
}
There's an issue tracking adding this as an option for the straightforward cases.
Related
I am trying to understand in depth how 'this' works in javascript.
All I have known about this so far is,
Every function has properties and whenever the function executes, it newly defines the this property.
this refers to the object that a function is invoked to (including window object in browser).
this refers to the scope of the object(where the object is defined) instead of referring to the object itself if you use arrow syntax when defining a function because arrow function does not newly defines its own this.
The examples below are to help understanding the behaviour of this
class Example {
constructor() {
this.name = 'John';
}
method1() { //case1 : Closure
console.log(this.name);
function method2() {
console.log(this.name);
}
method2();
}
}
const a = new Example()
a.method1();
function testing(callback) {
return callback();
}
class Example2 {
constructor() {
this.name = 'John';
}
method1() { //case2: callback
console.log(this.name);
testing(function() {
console.log(this.name);
})
}
}
const b = new Example2()
b.method1();
function testing(callback) {
return callback();
}
class Example3 {
constructor() {
this.name = 'John';
}
method1() { //case3: arrow syntax callback
console.log(this.name);
testing(() => {
console.log(this.name);
})
}
}
const c = new Example3()
c.method1(); // logs 'John'
// logs 'John'
function testing(callback) {
return callback();
}
class Example4 {
constructor() {
this.name = 'John';
}
method1() { // case4: calling method as callback
console.log(this.name);
}
render() {
testing(this.method1)
}
}
const d = new Example4()
d.render()
function testing(callback) {
return callback();
}
class Example5 {
constructor() {
this.name = 'John';
this.method1 = this.method1.bind(this);
}
method1() { //case5: bind method && calling method as callback
console.log(this.name);
}
render() {
testing(this.method1)
}
}
const d = new Example5()
d.render()
I wonder how those above cases are different and what the this refers to inside each inner function and callback. Could you please explain about it? thank you :)
Since the in-depth precise explanation can be pretty big and boring, here is an exceptional article by kangax that perfectly lays it out.
And just in case, if you need a short and ultra condensed version of it here goes my short and approximate take:
#
When you call a function the this is determined by the specific base value which is usually pointing to whatever is on the left of the .
in MemberExpression so in x.y() this === x, and in x.y.z() this === x.y.
In case of a simple CallExpression without the ., say just x(),
the base value is implicitly inferred to point to undefined, which in non-strict mode is converted to global window and in strict mode stays the same.
This is the general mental model which should cover 99% of all the day-to-day problems with drawing the this context out correctly.
Now on, to the actual cases:
CASE 1:
a.method1(); call has a base value a so the this inside of its body points to a, so no surprises here.
method2 has implicit base value undefined.method2, thus you have the TypeError which explicitly states that.
CASE 2:
function testing(callback) {
return callback();
}
callback() is called with implicit baseValue undefined, i.e. undefined.callback(),
and since the passed function is declared within class
testing(function() {
console.log(this.name);
})
that triggers the strict mode of code execution, that's why undefined is not converted again to global window, thus we have the same error as before.
CASE 3:
Arrow function
testing(() => {
console.log(this.name);
})
creates a hard binding from the this in enclosing scope,
basically under the hood it's the same as writing:
var _this = this;
testing((function() {
console.log(_this.name);
});
That's why you get the same object resolved as this
CASE 4:
Alright, this one is interesting and needs more mechanics explanation.
So when you pass this.method in:
render() {
testing(this.method1)
}
what you actually pass is not the reference this.method, but the actual underlying Function Object value, to which this reference points to, so
when it gets executed it has its this always pointing to undefined, here look, so it's pretty much "in stone".
And yes of course since this.method1 is declared in strict context again, thanks to enclosing es6 class, undefined remains undefined without conversion to global window.
CASE 5:
Same mechanics as with arrow function. Bind creates a wrapper function, which holds the cached this value, which is not possible to override with .call and .apply, the same as in => function.
Hope this clarifies a bit it all a bit.
Reassigning values to incoming parameters is not recommended. Use temporary local variables instead.
Code clarity. By some, it is considered an ill approach to assign values to parameters within a method's body, as it is, at times, confusing. Some developers prefer always assuming that a parameter is never assigned any value during a method's run.
public class Foo {
private void foo(String bar) {
// ...
bar = "something else";
// ...
}
}
You expect bar to be a value given by the caller, and it is overwritten instead. You can easily rephrase this to avoid pmd warning:
public class Foo {
private void foo(String bar) {
String myBar = bar;
// ...
myBar = "something else";
// ...
}
}
I'm new to TypeScript but have a background in C# and I'm a little bit confused about how to handle TypeScript modules. I've been thinking about modules as namespaces in C# but maybe this is wrong because my code doesn't behave the way I was expecting.
I have the following folder structure:
|-myApp
| |-myController
| | |-myController.ts
| |-models
|-a.ts
|-b.ts
and this code:
// a.ts
module MyApp.Models {
export class A {
}
}
// b.ts
module MyApp.Models {
export class B {
}
}
// myController.ts (THIS DOESN'T WORK)
module MyApp.MyController {
import Models = MyApp.Models;
class MyController {
a = new Models.A();
b = new Models.B();
}
}
// myController.ts (THIS WORKS)
module MyApp.MyController {
class MyController {
a = new Models.A();
b = new Models.B();
}
}
In the example above my attempt at importing the module (namespace?) Models will result in an error at runtime because Models is undefined. However if I remove the import-statement the code will works just fine. I'm probably not thinking clearly and doing some really stupid beginners mistake but could someone please tell me what I'm doing wrong and what the best way to use modules in my particular scenario would be. Why does it work if I remove the import but not with it?
Regards Kristofer
Sorry for late answer.
Problem and magic around modules/namespaces are occurred in three things:
Your system - due to your system TypeScript compiler discover files by difference ways, and when it compile your source code to JS code it take a place, because the same ts files provide different results JS.
Understanding magic statement /// <reference path="***"/>. It is very important use this word if there are no additional Module System like AMD, or System.js, etc. Because if you use merged compilation it take place, because it tell compiler in what order it should compile files.
Understanding of JS execution and structure that TypeScript propose in compiled JS file. Just consider next example - (it is your compiled into JS example)
var MyApp;
(//functon wrapping
function (MyApp) {//function declaration
var MyController;
(function (MyController_1) {
var Models = MyApp.Models;
var MyController = (function () {
function MyController() {
this.a = new Models.A();
this.b = new Models.B();
}
return MyController;
})();
MyController_1.MyController = MyController;
})(MyController = MyApp.MyController || (MyApp.MyController = {}));
}
)(MyApp || (MyApp = {}));// end of function wrapping and it execution
/// <reference path="myApp/MyController/myController.ts"/>
new MyApp.MyController.MyController(); // createing new instance of MyController
var MyApp;
(function (MyApp) {
var Models;
(function (Models) {
var B = (function () {
function B() {
}
return B;
})();
Models.B = B;
})(Models = MyApp.Models || (MyApp.Models = {}));
})(MyApp || (MyApp = {}));
var MyApp;
(function (MyApp) {
var Models;
(function (Models) {
var A = (function () {
function A() {
}
return A;
})();
Models.A = A;
})(Models = MyApp.Models || (MyApp.Models = {}));
})(MyApp || (MyApp = {}));
//# sourceMappingURL=app.js.map
if you dive deeper into JS you would find that the JS code is executing in the next order
Reading function and passing it into the memory
Executing another code
That is why the next code would work
myFunction();
function myFunctuion(){};
Due to typescript JS building technics for modules and classes it use anonimous function like this:
var MyApp;
(//functon wrapping
function (MyApp) {//function declaration
var MyController;
(function (MyController_1) {
var Models = MyApp.Models;
var MyController = (function () {
function MyController() {
this.a = new Models.A();
this.b = new Models.B();
}
return MyController;
})();
MyController_1.MyController = MyController;
})(MyController = MyApp.MyController || (MyApp.MyController = {}));
In this case calling like next cause runtime exception, because anonimus block has not executed before.
MyController(); // here runtime exception
var MyController = (function () {
function MyController() {
this.a = new Models.A();
this.b = new Models.B();
}
return MyController;
})();
Now, back to the our example and discover it, as you see MyController defined earlier, than we do execution of anonymous function and variable with name MyController now exist in the global scope.
The next step is executing constructor of MyController class, in it we find next two part of code
this.a = new Models.A();
this.b = new Models.B();
But here we get an error because the anonymous function that consist variable Modules and classes A and B has not executed yet. That is why, in this moment we getting the error that variable Modules is undefined.
I hope that this topic make your knowledge about JS and TS better, and help you in your new features!!!
Good Luck!
P.S. Here is working example
Typescript modules are similar to C# namespaces. They help organize the codebase.
The import statement can be used for two things: to provide an alias or to import external modules.
To create an alias you use the import as you did:
import Models = App.Models;
To import an external module you use:
import Models = './path/to/module';
I can't figure out why your code doesn't work. I tried to reproduce it on my machine but both controllers work for me.
I've detected a very weird behavior in coffeescript.
class Foo
list: []
add: (val)->
#list.push(val)
x = new Foo()
x.add(1)
console.log(x.list.length) // 1
y = new Foo()
y.add(1)
console.log(y.list.length) // 2
So as you see the #list property got shared between the two class instances in a strange way.
I've never faced similar issue before, in coffeescript.
Convert it to JavaScript:
var Foo, x, y;
Foo = (function() {
function Foo() {}
Foo.prototype.list = [];
Foo.prototype.add = function(val) {
return this.list.push(val);
};
return Foo;
})();
As you can see, Foo.prototype.list is a property of the prototype, not of an instance of your class. There's only one array and it will be shared across all of the instances of your class.
To make list an instance variable, add it to the constructor:
class Foo
constructor: ->
#list = []
add: (val)->
#list.push(val)
I'd like to be able to parametrize my exports not only with types (as in, generic exports), but also with values.
Something like:
class Greeter
{
readonly string _format;
public Greeter( string format ) { _format = format; }
public string Greet( string name ) { return string.Format( _format, name ); }
}
// ...
var e = new ExportProvider();
e.ExportParametrized<Greeter>( args: new[] { "Hi, {0}!" } );
e.ExportParametrized<Greeter>( args: new[] { "¡Hola, {0}!" } );
// And then:
[ImportMany] IEnumerable<Greeter> Greeters { get; set; }
foreach( var g in Greeters ) Console.WriteLine( g.Greet( "John" ) );
// Should print out:
// Hello, John!
// ¡Hola, John!
One might ask: why don't I simply export the value new Greeter( "Hello, {0}!" ) using ComposablePartExportProvider and CompositionBatch?
While this approach would work in this particular case, it has an important flaw: if the Greeter class had any imports of its own, they would not be satisfied.
The usual way I would go about this is to declare two classes - EnglishGreeter and SpanishGreeter, inherit them both from Greeter, and then provide the appropriate arguments in the call to base constructor.
But this doesn't work for two reasons:
This is a lot of noise to write. Not only do I have to type the whole shebang, I also have to come up with names for those classes, and it doesn't always make sense to have names. Not to mention the DRY principle. But even besides the noise...
Sometimes I don't know the parameters upfront. Say, for example, my greeting formats were coming from some kind of config file.
Here is another thought, to somewhat clarify what I'm looking for.
This problem is almost solved in the TypeCatalog. See, the TypeCatalog knows about the type and it calls the type's constructor to create the part on demand.
One can think of this process from another standpoint: the catalog has a factory function; using that function, it creates the part, then satisfies its non-prerequisite imports, and then returns the part back to the requestor.
Now, in the particular case of TypeCatalog, the factory function just happens to be the type's own constructor. If only I could hook in and replace the factory function with my own, but still leverage the rest of the machinery, that would be exactly what I'm looking for.
You can achieve this by using property exports. You could define a class specifically for those kinds of exports, and it will look like this:
class MyParameterizedExports
{
[Export(typeof(Greeter))]
private Greeter EnglishGreeter
{
get
{
Greeter g = new Greeter("Hi, {0}!");
container.SatisfyImportsOnce(g);
return g;
}
}
[Export(typeof(Greeter))]
private Greeter SpanishGreeter
{
get
{
Greeter g = new Greeter("¡Hola, {0}!");
container.SatisfyImportsOnce(g);
return g;
}
}
}
Here you export two separate Greeter instances without having to define a new class for each type of Greeter.