In my angular2 project I'm trying to extend the prototype of the string class using typescript. This is my code:
interface String
{
startsWith(s:string);
contains(s:string);
containsOr(s1:string, s2:string);
}
String.prototype.startsWith = function (s:string):boolean {
return this.indexOf (s) === 0;
}
String.prototype.contains = function (s:string):boolean {
return this.indexOf(s) > 1;
}
String.prototype.containsOr = function (s1:string, s2:string):boolean {
return this.indexOf(s1) > 1 || this.indexOf (s2) > 1;
}
With this code the project compiles (also the content assist of Visual Studio Code assists me) but at run-time I get a 'contains is not defined'.
What I'm doing wrong?
Thanks a lot
PS: this is my tsconfig:
{
"compilerOptions": {
"target": "es5",
"module": "system",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": false,
"outDir": "wwwroot/app/source/"
},
"exclude": [
"node_modules",
"bower_components",
"wwwroot",
"typings/main",
"typings/main.d.ts"
]
}
EDIT
I noticed that importing the js file in index.html it works, but I don't like this approach.
<script src="app/source/utils/extensions.js"></script>
Extension-method gives you the power to add new methods to existing types. You don't have to create a new derived-type. You can write extension-method of any data-type you want.
Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. Extension methods are static methods, but they're called as if they were instance methods on the extended type.
LinqExtensionMethod.zip. Linq provides standard query operators like filtering, sorting, grouping, aggregation, and concatenations, and it has many operators to achive many types of functionalities, which are called extension methods, in LINQ.
Just like object-oriented languages such as Java and C#, TypeScript classes can be extended to create new classes with inheritance, using the keyword extends . In the above example, the Employee class extends the Person class using extends keyword.
I was able to get it working with no TS errors (1.8.9), Angular2 (2.0.0-beta.12) errors, and working function call using the following template:
tsconfig.json
{
"compilerOptions": {
"target": "es5",
"module": "system",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": false
},
"exclude": [
"node_modules",
"typings/main",
"typings/main.d.ts"
]
}
Next, create (if one doesn't exist) a global.d.ts file local to your project:
global.d.ts (local to project, not main TS file of same name)
export {}
declare global {
interface String {
calcWidth(): number;
}
}
extensions.ts (entire file)
export {}
//don't redefine if it's already there
if (!String.prototype.hasOwnProperty('calcWidth')) {
String.prototype.calcWidth = function (): number {
//width calculations go here, but for brevity just return length
return this.length;
}
}
Then in your whatever your first System.import(filename) is (mine is main.ts). Just use once:
import './extensions' //or whatever path is appropriate
...
...
Now, throughout your app you can use your interface:
var testString = 'fun test';
console.log(testString.calcWidth());
Produces console output:
8
Hope this is helpful.
Instead of importing the code in html just put this at the top of your code:
import './utils/extensions';
Just replace it with your path to the file.
Here are some more resources on modules and imports:
TypeScript docs
MDN docs
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With