Why might TypeScript not be enforcing a type declared for a class property? - class

This is on a large code base, so I'm just looking for general pointers.
In one file, a function takes a parameter a:MyClass.
At runtime, typeof a.b yields string.
In VSCode I hit F12 on the b of a.b and am brought (correctly, judging by the import statement) to another file:
export class MyClass {
...
b: string[]; // brought to this line
}
How is it possible within a TypeScript environment for a.b to be a string instead of a string[] like the class declaration says? And what should I look for that might cause this behaviour?

Type declarations in TypeScript are only suggestive. Because TypeScript is transpiled into plain JavaScript it can not make any guarantees about the actual content of a variable.
Even in TypeScript itself is fairly easy to put an object of a different type in a variable:
let myClass = new MyClass();
myClass.b = "I'm a string placed into a string array" as any;
Notice the as any at the end of the last line, this removes type information from an expression and allows it to be placed into a variable or argument of any type.

Related

Extending the prototype of a built-in class in Typescript 2.8+

This doesn't work
interface String {
contains(s:string):boolean;
}
String.prototype.contains=(s:string):boolean=>this.indexOf(s)!==-1;
because Property 'contains' does not exist on type 'String'
This is a bit of a surprise since adding it was the entire point of the interface declaration. http://www.typescriptlang.org/docs/handbook/declaration-merging.html suggests that the above code is legal. String is in the global namespace as far as I can tell by examining lib.es2015.wellknown.d.ts.
What's the right way to go about this? After reading Aluan Haddad's Extending third party module that is globally exposed I rewrote like this
declare global {
interface String {
contains(s: string): boolean;
}
}
String.prototype.contains=(s:string):boolean=>this.indexOf(s)!==-1;
and the interface change is now correct. But now 'this' implicitly has type 'any' because it does not have a type annotation.
Per further comments this can be explicitly typed using function syntax.
String.prototype.contains = function (this: string, s:string):boolean {
return this.indexOf(s)!==-1;
};
It should also be noted that in the course of this investigation I discovered that contains is implemented with the name includes and is declared in lib.es2015.core.d.ts
If you're defining the augmentation inside of a module, that is a file containing a top-level import or export then you need to use a declare global block in order to augment the global scope. Otherwise, the interface that you declare will not be merged into the global array interface because it's local to the module like any other declaration would be. The declare global syntax is specifically to cover this use case.
Furthermore, when you define the actual method you can't use an arrow function if the method itself is defined in terms of this because Arrow functions have a statically scope this while a dynamic this is needed for methods.
Putting it together
// this is a module
export {}
declare global {
interface String {
contains(other: string): boolean;
}
}
String.prototype.contains = function (other) {
return this.indexOf(other) and !== -1;
};
Note that whether the type being augmented is a class or an interface, the member needs to be declared in an interface as above because interfaces can merge with classes and interfaces can merge with interfaces but classes do not merge.

Mark Haxe Class for forced extend?

Is there a compiler meta for Class declaration, that prevents creating Class instance before extending it? In other words - some sort of opposite of #:final meta.
Like so (last line of code):
class A {
// ...
}
class B extends A {
// ...
}
// ...
var b = new B(); // OK
var a = new A(); // induce compiler-error
Simply don't declare a constructor at all for class A
Both the other answers are correct (no constructor or private constructor), but there are a few more details that you may interest you:
Here's an example of no constructor. Of note is that A simply doesn't have a constructor, and B simply doesn't call super(). Other than that, everything else works as you'd expect.
Here's an example of a private constructor. You still can't instantiate a new A(), but you do still need to call super() from B's constructor.
Technicalities:
Use of some features (like a default value on a member variable) will cause A to get an implicit constructor, automatically. Don't worry, this doesn't affect constructability or whether you need to call super(). But know that it is there, and if necessary an implicit super() call is prepended to B's constructor. See the JS output to verify this.
In any case, know that you can still instantiate an A at runtime with var a = Type.createInstance(A,[]); as compile-time type checks do not limit RTTI.
Related discussion:
Aside from private/no constructor, Haxe doesn't have a formal notion of abstract classes1 (base classes not expected to be instantiated) or abstract methods2 (functions on abstract base classes with no implementation that must be implemented by a derived class.) However, Andy Li wrote a macro for enforcing some of those concepts if you use them. Such a macro can detect violations of these rules and throw compile-time errors.
1. Not to be confused with Haxe abstracts types, which are an entirely different topic.
2. Not to be confused with virtual functions, which wikipedia describes as a function which can be overridden (though various docs for various languages describe this highly loaded term differently.)
One way of achieving this is to create private Class constructor:
class A {
private function new() {
// ...
}
}
// ...
var a = new A(); // Error: Cannot access private constructor

Scala parameters for access modifiers?

What is the difference between
class Test {
private[this] val foo = 0
}
vs
class Test {
private val foo = 0
}
What all can go inside the []? Also, what should I search for when I want to look up the specs of this? I tried Googling various combinations of "scala access modifier arguments/parametrized scala access modifier" and nothing came up.
what should I search for when I want to look up the specs of this?
In The Scala Language Specification it is defined as "access modifier" and "access qualifier" (see BNF in §5.2).
What is the difference between
...
What all can go inside the []?
You can put class name, package name or this there. Here is a relevant quote from language specs that explains this (see §5.2 for more details):
The modifier can be qualified with an identifier C (e.g. private[C ]) that must
denote a class or package enclosing the definition. Members labeled with
such a modifier are accessible respectively only from code inside the package
C or only from code inside the class C and its companion module (§5.4).
An different form of qualification is private[this]. A member M marked
with this modifier is called object-protected; it can be accessed only from
within the object in which it is defined. That is, a selection p.M is only legal if the prefix is this or O.this, for some class O enclosing the reference. In
addition, the restrictions for unqualified private apply.
The first one is private for instance class, second is for class. If you use second version you have access from another instance of Test class (it's usefull for equals method or similiar).

Using mixins in Coffeescript

I want to split up a large class by using mixins.
I am using this mixin code from the Little Book
#include: (obj) ->
for key, value of obj when key not in moduleKeywords
# Assign properties to the prototype
#::[key] = value
obj.included?.apply(#)
this
class FooMixin
b: => #something = 2
class Foo extends Module
#include FooMixin
a: => #something = 1
Problem is that # in FooMixin is FooMixin. I want it to be Foo instead.
I have tried adding the line _.bind(#::[key], #) at the end of #include() but it doesn't help. Any suggestions?
Okay, few things I was doing wrong.
1.
#include from the Little Book takes an object not a class. To get it to work with classes you need to write #include FooMixin::. However, I have since begun using objects instead.
2.
When using an object instead of a class, the fat arrow adds a line inside the CoffeeScript wrapper right at the top which reads _this = this. All methods are bound to the global context which is not what we want. To fix we must convert fat arrows to thin arrows, and bind each function to our Foo instance. Using Underscore I added this to the constructor of Foo:
constructor: ->
for fname in _.functions FooMixin
#[fname] = _.bind #[fname], #
super
I tried _.bindAll #, _.functions FooMixin but it gave me an error saying something like At Function.bind, could not run bind of undefined. Weird error, seeing as the code above is pretty much identical to the _.bindAll method.
So now I can split my classes up for better readability and code sharing.
UPDATE: The problem with _.bindAll is that it takes a splat not an array. Fix is to use _.bindAll #, _.functions(FooMixin)....
UPDATE: Found a better solution.
Same as original post. Use classes for mixins.
Use #include FooMixin:: or change #include to operate on a prototype instead of properties.
In the Foo constructor write FooMixin.call # which binds the methods correctly.
This works well and is nice and clean.
The only potential issue is that mixins will be overridden by existing properties. The only way to get around this that I can see is to do something like:
after = ->
_.extend Foo, FooMixin::
class Foo
# define...
after()
Or pass the extend method to _.defer but this is so hacky and probably won't work.

How to properly set up a class that inherits from another in Scala?

I have been looking at examples online, and tutorials, and I cannot find anything that explains how this (inheritance) differs from java. Simple example:
class Shape {
String type;
Shape(String type) {
this.type = type;
}
...
}
class Square extends Shape {
Square(String name){
Super(name);
}
....
}
Whats confusing me is in the above example I need to call the super class in order to set the 'type' variable, as well as to access it to tell me the Box objects' type as well. In Scala, how can this be done? I know scala uses traits interfaces as well, but is the above example omitted completely from scala? Can anyone direct me to a good example or explain it. I really appreciate it.
You can write almost exactly the same thing in Scala, much more concisely:
class Shape(var `type`: String)
class Square(name: String) extends Shape(name)
In the first line, the fact that type is preceded by var makes the compiler add getters and setters (from "5.3 Class Definitions" in the specification):
If a formal parameter declaration x : T is preceded by a val or
var keyword, an accessor (getter) definition (§4.2) for this parameter is implicitly added to the class. The getter introduces a value member x of class c that is defined as an alias of the parameter. If the introducing keyword is var, a setter accessor x _= (§4.2) is also implicitly added to the class.
In the second line name is not preceded by val or var, and is therefore just a constructor parameter, which is this case we pass on to the superclass constructor in the extends clause. No getters or setters are added for name, so if we created an instance square of Square and called square.name, it wouldn't compile.
Note also that type is a keyword in Scala, so I've had to surround it by backticks in both the definition and the example above:
Example 1.1.2 Backquote-enclosed strings are a solution when one needs to access Java identifiers that are reserved words in Scala.
There are many, many resource that you can read for more information about inheritance in Scala. See for example Chapters 4 and 5 of Programming Scala.