Extending functionality in TypeScript [duplicate] - javascript

This question already has answers here:
Closed 10 years ago.
The community reviewed whether to reopen this question 5 months ago and left it closed:
Original close reason(s) were not resolved
Possible Duplicate:
How does prototype extend on typescript?
I am currently learning TypeScript, and would like to know how it is possible to add functionality to existing objects. Say I want to add an implementation for Foo to the String object. In JavaScript I would do this:
String.prototype.Foo = function() {
// DO THIS...
}
Understanding that TypeScript classes, interfaces and modules are open ended led me to try the following, without success
1. Reference the JavaScript implementation from TypeScript
JavaScript:
String.prototype.Foo = function() {
// DO THIS...
}
TypeScript:
var x = "Hello World";
x.Foo(); //ERROR, Method does not exist
2. Extend the interface
interface String {
Foo(): number;
}
var x = "Hello World";
x.Foo(); //Exists but no implementation.
3. Extend the class
class String {
Foo(): number {
return 0;
}
}
// ERROR: Duplicate identifier 'String'
As you can see from these results, so far I have been able to add the method via an interface contract, but no implementation, so, how do I go about defining AND implementing my Foo method as part of the pre-existing String class?

I have found the solution. It takes a combination of the interface and the JavaScript implementation. The interface provides the contract for TypeScript, allowing visibility of the new method. The JavaScript implementation provides the code that will be executed when the method is called.
Example:
interface String {
foo(): number;
}
String.prototype.foo= function() {
return 0;
}
As of TypeScript 1.4 you can now also extend static members:
interface StringConstructor {
bar(msg: string): void;
}
String.bar = function(msg: string) {
console.log("Example of static extension: " + msg);
}

Related

TypeScript - using recursive generics properly [duplicate]

This question already has answers here:
How do I declare object value type without declaring key type?
(2 answers)
Closed 12 months ago.
I am trying to use recursive generics in a way I can get a lot of help from editor.
Here is an example:
interface ServiceEndpointNode {
self: string;
context?: Record<string, ServiceEndpointNode>
}
const ServiceEndpoints: ServiceEndpointNode = {
self: 'BASE_URL',
context: {
songs: {
self: 'GET_SONGS',
context: {
getSong: {
self: 'GET_SONG',
},
getContributors: {
self: 'GET_CONTRIBUTORS',
}
}
}
}
}
This works properly and the structure is strict, but I don't got help from the editor. For example I want help like:
ServiceEndpoints.context.songs.context.getsong.self
But because I only told the typing that the context should be a string I don't really receiving help about the traversable object. I guess I need to be include some generics or something, but don't know how to achieve that. :(
So I want to have to maintain this strict structure, yet get help from the editor for all the possible routes, keys, etc.
Now you can use Optional chaining in TypeScript simplify as shown below. So that typescript compiler will expect NULL | underfined
console.log(ServiceEndpoints.context?.songs.context?.getSong?.self);
// OUTPUT: "GET_SONG"

Typescript: calling static methods in constructor [duplicate]

This question already has answers here:
Access to static properties via this.constructor in typescript
(5 answers)
Closed 1 year ago.
here is an example of my class with the methods in question
class Example {
constructor(info) {
// call validateInfo(info)
}
static validateInfo(info):void {
// validate the info
}
I would like to call validateInfo in the constructor, but I can't just do this with this.validateInfo(info) because it is a static method.
In Javascript, I could do this:
constructor(info) {
this.constructor.validateInfo(info)
}
but, in Typescript this gives the following error:
error TS2339: Property 'validateInfo' does not exist on type 'Function'.
I understand the error message, but is there a Typescript equivalent for the Javascript solution?
The problem is that a subclass may have called the constructor, not Example. I'd reference Example specifically:
constructor(info) {
Example.validateInfo(info)
}
Another option to consider would be making it a normal method rather than a static method.

How to get an interface's properties from typescript [duplicate]

This question already has answers here:
Is there a way to "extract" the type of TypeScript interface property?
(5 answers)
Closed 2 years ago.
I want to get a "postType" Property from an interface defined like this
export interface PostType {
postType: {
title?: string;
content?: string;
};
}
The purpose I want to take out and use the "postType" Property is as follows
const fn = (post: Post) => {
...
}
I used "Pick" but this doesn't work.
export type Post = Pick<PostType, 'postType'>;
The reason I've configured the interface above is that PostType is actually a property that corresponds to another interface.
So I have to follow PostType's interface.
How can I do this?
If I understand correctly you want to do this: PostType["postType"]

Accessing 'this' inside Typescript raw function [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 4 years ago.
I have an Angular 6 app that uses the excellent ngx-charts framwork to display charts. This charting component lets me specify a tooltip formatting function like so:
<ngx-charts-bar-vertical [xAxisTickFormatting]="dateTickFormatting" >
</ngx-charts-bar-vertical>
And then define the formatting function in the parent component class:
dateTickFormatting(val: string): string {
return val.toUpperCase();
}
My problem happens when I try to access values in the parent component class from this formatter function:
public testVar: string = 'This is a test variable';
dateTickFormatting(val: string): string {
console.log(this.testVar);
return val.toUpperCase();
}
In this case, testVar will be undefined.
I understand that the 'this' reference is lost because ngx-charts is referencing dateTickFormatting as a 'raw' function. Is there a way to preserve a reference to the parent classes' this, barring modifications to the charting framework?
You should use arrow functions
If you do
public testVar: string = 'This is a test variable';
dateTickFormatting = (val: string): string => {
console.log(this.testVar);
return val.toUpperCase();
}
It will use the correct this and work.
I recommend reading a bit about arrow functions https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

How to call super/base methods in JavaScript? [duplicate]

This question already has answers here:
Emulate super in javascript
(11 answers)
Closed 8 years ago.
I have to implement following code in Javascript, but cannot find equivalent of super.say() in javascript. How to do this translation ?
class Foo {
public void say() {
System.out.println("foo");
}
}
class Bar extends Foo {
static int counter = 0;
public void say() {
super.say();
counter++;
System.out.println("bar " + counter);
}
}
There's an article that describes it in detail: http://joshgertzen.com/object-oriented-super-class-method-calling-with-javascript/
Basically, you need to store a reference to your base method, then call it in the "derived" (perhaps "shadowed" might be a better word here) method.
The keyword super doesn't work in Javascript as in Java because there's no notion of classes. Without a class, you can't have a descendant, and thus super is useless in that context.
You could implement something super-like, as described here.

Categories