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

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.

Related

Why does nesting a class give the containing class access to the child class' protected data?

The question may be a bit confusing, and is best illustrated by an example:
unit Test
interface
type
TestClass = class()
Splitter1: TcxSplitter;
procedure SomeMethod();
end;
implementation
uses
cxSplitter;
// Locally-declared child type
type
TcxSplitterAccess = class(TcxSplitter);
procedure TestClass.SomeMethod()
var
pos: integer;
begin
// Access to protected field FPositionBeforeClose by casting
pos := TcxSplitterAccess(Splitter1).FPositionBeforeClose;
end;
Notice in the implementation section that there is a type TcxSplitterAccess being declared as a child of the TcxSplitter class. In the method SomeMethod(), belonging to the class TestClass, a TcxSplitter object is cast to the locally-declared TcxSplitterAccess class, and then a protected field is accessed on that object.
This is surprising to me as someone coming from a background of languages like Java, C++, C#, etc. In those languages, it is possible to access protected data in an object so long as you are doing it from within that object's type or an inherited type. For example, a method inside of a class ClazzA can access the private fields of other ClazzA objects since access is enforced at the type level rather than the instance level. Declaring a class locally in these languages would not give the containing class access to the local class' protected data (edit: As pointed out in the comments, this is actually not true at least for Java).
In this example, however, the type TestClass is directly accessing a protected field on the TcxSplitter object by first casting to the TcxSplitterAccess type. I am having trouble finding documentation on why this "trick" works. Does Delphi handle access levels fundamentally differently to Java-like languages and allows this sort of thing? Regardless, why does this trick work?
While I stumbled onto this behavior by using a nested, inherited class in order to access fields on the parent class (which breaks encapsulation, and I shouldn't do), the use of inheritance here is unnecessary. If the nested class did not inherit from a class, but instead had its own protected fields defined, TestClass would still be able to access those protected fields.
A unit has implicit-friendship semantics within itself. Types declared in the same unit are "friends" of each other (similar to friend in C++), and so can access each other's private and protected members (but not strict private or strict protected members).
So, in this case:
TcxSplitterAccess derives from TcxSplitter, so TcxSplitterAccess inherits all of the protected (but not private) members of TcxSplitter via normal class inheritance.
TestClass is declared in the same unit as TcxSplitterAccess, so TestClass has access to all of the protected members of TcxSplitterAccess, including the protected members of TcxSplitter (and the protected members of its ancestors).
FPositionBeforeClose is protected in TcxSplitter.
So, that is why TestClass.SomeMethod() is able to access FPositionBeforeClose when type-casting the Splitter1 object to TcxSplitterAccess.
This is covered by the Delphi documentation:
Private, Protected, Public, and Published Declarations
Classes and Objects (Delphi): Visibility of Class Members

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

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

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.

What is the Guiding Principle of Access Levels meaning in swift

The Guiding Principle of Access Levels of swift is
No entity can be defined in terms of another entity that has a lower (more >restrictive) access level.
For example:
A public variable cannot be defined as having an internal or private type, because the type might not be available everywhere that the public variable is used.
A function cannot have a higher access level than its parameter types and return type, because the function could be used in situations where its constituent types are not available to the surrounding code.
could any body show me a code example about
A public variable cannot be defined as having an internal or private type, because the type might not be available everywhere that the public variable is used.
and
A function cannot have a higher access level than its parameter types and return type, because the function could be used in situations where its constituent types are not available to the surrounding code.
I don't know the clearly meaning of the principle of access level
Accessibility levels are, in increasing order:
private - only this file/class
internal - only this module
public - anybody
You can't use
private class Foo {
}
public var myFoo:Foo
because myFoo is visible outside the module but class Foo isn't, therefore anybody using myFoo wouldn't know what to do with it, how big it was, etc. If you change myFoo to private, then it's all good because anybody that has access to myFoo also has access to class Foo.
Likewise, you can't use:
private class Foo {
}
public func getMyFoo() -> Foo {...}
for the same reasons, the caller of getMyFoo doesn't (can't) know what Foo is, so has no way to properly deal with it.
Essentially if a type is private (or not public) then there can't be any external visibility of objects of that type.
Here are some simple examples:
internal protocol InternalProtocol { }
class MyClass {
// V~~~ This won't work, because InternalProtocol is internal, but the variable is public
public let myInternalProtocolVariable: InternalProtocol
// V~~~ This won't work because InternalProtocol is internal, but the function is public
public func publicFunc(ip: InternalProtocol) -> InternalProtocol {
return ip
}
}
The idea is that the caller of the function, or the object accessing the variable has to have access to the types that are used in the function or the variable.
If the user doesn't have access to InternalProtocol - i.e., they can't "see" it - then they shouldn't be able to "see" any variables or functions that use that type either.

what is the meaning of `Class of ` type declaration?

While going through one of my code, I am stuck on one statement which is as below.
TMyObjectClass = class of TMyObject;
I am a bit confused, and wondering what is the meaning of this statement.
As TMyObjectClass has no declaration above the statement.
and TMyObject is having declaration as below:
TMyObject = class(TObject)
private
//some private member declaration
Public
// some public variables
end;
So, my question is what is the meaning of the statement
TMyObjectClass = class of TMyObject;
and How TMyObjectClass works?
I am a bit new to Delphi, so please help me to get some idea about these type of declaration and there workarounds.
This is a Class Reference.
They are used to work with meta classes. The canonical example is the Delphi streaming framework which uses
TComponentClass = class of TComponent;
This allows for dynamic binding to virtual constructors. The TComponent constructor is virtual. The streaming framework needs to instantiate classes derived from TComponent. It does so something like this:
var
ComponentClass: TComponentClass;
Component: TComponent;
....
ComponentClass := GetComponentClassSomehowDoesntMatterHow;
Component := ComponentClass.Create(Owner);
Now, because TComponent.Create is virtual, this is bound in a polymorphic fashion. If TComponentClass is TButton, then TButton.Create is called. If TComponentClass is TPanel, then TPanel.Create is called. And so on.
The most important thing to realise is that the class that is constructed is determined only at runtime. Note that many languages lack this capability, most notably C++.