I just found the answer to this in another Stack Overflow question's answer.
declare global {
interface Window { MyNamespace: any; }
}
window.MyNamespace = window.MyNamespace || {};
Basically, you need to extend the existing window
interface to tell it about your new property.
TypeScript uses getter/setter syntax that is like ECMAScript4/ActionScript3.
class foo {
private _bar: boolean = false;
get bar(): boolean {
return this._bar;
}
set bar(value: boolean) {
this._bar = value;
}
}
That will produce this JavaScript, using the ECMAScript 5 Object.defineProperty()
feature.
var foo = (function () {
function foo() {
this._bar = false;
}
Object.defineProperty(foo.prototype, "bar", {
get: function () {
return this._bar;
},
set: function (value) {
this._bar = value;
},
enumerable: true,
configurable: true
});
return foo;
})();
So to use it,
var myFoo = new foo();
if(myFoo.bar) { // calls the getter
myFoo.bar = false; // calls the setter and passes false
}
However, in order to use it at all, you must make sure the TypeScript compiler targets ECMAScript5. If you are running the command line compiler, use --target
flag like this;
tsc --target ES5
If you are using Visual Studio, you must edit your project file to add the flag to the configuration for the TypeScriptCompile build tool. You can see that here:
As @DanFromGermany suggests below, if your are simply reading and writing a local property like foo.bar = true
, then having a setter and getter pair is overkill. You can always add them later if you need to do something, like logging, whenever the property is read or written.
Getters can be used to implement readonly properties. Here is an example that also shows how getters interact with readonly and optional types.
//
// type with optional readonly property.
// baz?:string is the same as baz:string|undefined
//
type Foo = {
readonly bar: string;
readonly baz?: string;
}
const foo:Foo = {bar: "bar"}
console.log(foo.bar) // prints 'bar'
console.log(foo.baz) // prints undefined
//
// interface with optional readonly property
//
interface iFoo {
readonly bar: string;
readonly baz?: string;
}
const ifoo:iFoo = {bar: "bar"}
console.log(ifoo.bar) // prints 'bar'
console.log(ifoo.baz) // prints undefined
//
// class implements bar as a getter,
// but leaves off baz.
//
class iBarClass implements iFoo {
get bar() { return "bar" }
}
const iBarInstance = new iBarClass()
console.log(iBarInstance.bar) // prints 'bar'
// accessing bas gives warning that bas does not exist
// on iBarClass but returns undefined
console.log(iBarInstance.bas) // prints 'undefined'
// note that you could define baz as a getter
// and just return undefined to remove the warning.
//
// class implements optional readonly property as a getter
//
class iBazClass extends iBarClass {
private readonly _baz?: string
constructor(baz?:string) {
super()
this._baz = baz
}
get baz() { return this._baz; }
}
const iBazInstance = new iBazClass("baz")
console.log(iBazInstance.bar) // prints bar
console.log(iBazInstance.baz) // prints baz
Best Answer
JavaScript is untyped, meaning that we can pass around and use data, objects and functions with no constraints. We can write code that calls methods that don't exist on an object, or reference variables that we don't have. These kinds of mistakes can be hard to discover when you are writing code, and it can lead to unstable and buggy code. Doing big changes of your code can become difficult and risky as you don't immediately see if some changes conflicts with the rest of the code somewhere else.
TypeScript is mainly about adding types to JavaScript. That means that TypeScript requires you to accurately describe the format of your objects and your data. When you do that, that means that the compiler can investigate your code and discover errors. It can see that you are trying to call a function with the wrong kinds of arguments, or reference a variable that is not accessible in the current scope.
When you write TypeScript yourself, this formal description of the code is part of the code itself.
However, when you use external libraries like jQuery or moment.js, there are no information of the types in that code. So in order to use it with TypeScript, you also have to get files that describe the types of that code. These are the type declaration files, most often with the file extension name
.d.ts
. Fortunately people have written those kinds of type declaration files for most common javascript libraries out there.Typings was just a tool to install those files. It is now best practice to just use npm.
When you have installed those files, which basically only means downloading them and placing them in your project, the TypeScript compiler will understand* that external code and you will be able to use those libraries. Otherwise you would only get errors everywhere.
* Depending on how you have set up your project and configured it, you might have to configure typescript to look for those files specifically, or it might just work without any configuration from your part.