A lot of TypeScript tutorials are available online, so I was looking for one recently and, it seems, this one is really good IF you are familiar with some other language already:
https://www.tutorialspoint.com/typescript
So, while working through it, I noticed a few things which might strike you as being somewhat unusual if you are more used to the languages like C# (or even javascript itself). Figured I’d come up with a short list to use as a refresher for myself later; although, if you are new to the TypeScript, you might find some of the items useful, too.
1. To declare a variable, we need to use <var_name>:<type_name> syntax
var x:number = 1
2. There is no need to use semicolons as long as we have one instruction per line
var x:number = 1
x = 2
x++
3. There are no separate numeric types
There is no int or double – all numbers are represented by the “number” type.
4. There are arrays and there are tuples
For an array, here is an example:
TS: var names:string[] = [“Mary”,”Tom”,”Jane”, “Andy”]
JS: var names = [“Mary”,”Tom”,”Jane”, “Andy”]
And here is an example for a tuple:
TS: var arr = [“Mary”,”Tom”,1, 2]
JS: var arr = [“Mary”,”Tom”,1, 2]
The difference between those two on the TS side is that arrays are strongly typed, so there will be type validation at compile-time. Tuples are not strongly typed, so you can put objects of different types into a tuple. Once compiled into JS, though, both arrays and tuples look the same.
5. Unions
This is a somewhat crazy concept which is basically saying that a variable can store values of more than one type, but those types have to be mentioned:
var val:string|number
val = 12
val = “This is a string”
Of course this means very little for the compiled javascript code, but it allows TypeScript to do compile-time type validations.
What’s unusual about this (besides the fact that I have not seen this concept in the .NET world so far) is that “union” has somewhat different meaning in other areas. For example, unions allows you to combine results from different queries in SQL, but those different queries since have to match each other on the “metadata” level (same columns). In case with the TypeScript, it’s the “metadata” which is becoming different through the use of the unions.
6. Interfaces
In TypeScript, an interface is more than a contract to be implemented by a class later. An interface defines a type that you can use in variable declarations:
interface IPerson {
firstName:string,
lastName:string,
}
var customer:IPerson = {
firstName:”Tom”,
lastName:”Hanks”,
}
In c#, you would have to implement the interface first through a class which inherits and implements the interface. In TS, you can declare a variable of the “interface type”, and you can implement that interface right there.
What I mean is that, in the example above, you can’t just omit one of the properties:
var customer:IPerson = {
firstName:”Tom”
}
Since you’ll get an error message from the compiler:
main.ts(6,5): error TS2322: Type ‘{ firstName: string; }’ is not assignable to type ‘IPerson’.
Property ‘lastName’ is missing in type ‘{ firstName: string; }’.
Also, there is a special construct for defining array interfaces – it seems I don’t fully understand the “index” part at the moment, so will just leave it at this:
interface namelist {
[index:number]:string
}
7. Somewhat special syntax when defining classes
- When defining class methods, we don’t use “function” keyword in TS
- When defining class properties, we don’t need to use “var” keyword
- To define a constructor, we need to use “constructor” keyword
- To reference a property in a function, we need to access that property through “this” object
class Car {
//field
engine:string;
//constructor
constructor(engine:string) {
this.engine = engine
}
//function
disp():void {
console.log(“Engine is : “+this.engine)
}
}
8. Type templates
There is a notion of type templates which basically means that, since every object in TS has to have a type, that type will be inferred from the variable declaration if you do it this way:
var person = {
firstname: “Tom”,
lastname: “Hanks”
}
With this, you can’t, now, dynamically add another property to the person:
person.age = 1
Since you’ll get an error:
main.ts(7,8): error TS2339: Property ‘age’ does not exist on type ‘{ firstname: string; lastname: string; }’
Instead, you have to add that age property to the original declaration somehow:
var person = {
firstname: “Tom”,
lastname: “Hanks”,
age: NaN
}
person.age = 1
9. Prototypes vs objects
When you have a class, all class methods will be defined in the prototype:
TS: class Car {
disp():void {
console.log(“Ford”)
}
}
Compiled JS:
var Car = /** @class */ (function () {
function Car() {
}
Car.prototype.disp = function () {
console.log(“Ford”);
};
return Car;
}());
And, then, you can actually change what “disp” means for a specific object of the class:
var a:Car = new Car()
a.disp = () => console.log(“Nissan”)
Which compiles into the following JS:
var a = new Car();
a.disp = function () { return console.log(“Nissan”); };
Well, that’s some strange stuff…
10. Namespaces
If you want to use a namespace from a different ts file, you have to reference the file:
/// <reference path = “SomeFileName.ts” />
There is a special “export” keyword which must be added to anything you want to be visible outside of the namespace.
Interestingly you can actually define the same namespace more than once in the same file:
namespace Test{
export interface Displayable {
disp():void;
}
}
namespace Test{
export class Car implements Displayable {
disp():void {
console.log(“Ford”)
}
}
}
var a:Test.Car = new Test.Car()
a.disp()
But, unless you’ve added those “export” keywords to the interface above and to the class, it’s not going to compile.
11. Modules
There is no equivalent concept in c#, it seems, so, for now, I’d rather just put a link to the page which seems to be explaining the concept… I’m still working through it
https://www.typescriptlang.org/docs/handbook/modules.html
12. Ambients
Essentially, it’s similar to adding a dll reference to your .NET project so that
- Typescript compiler could do compile-time validations
- You would not have to rewire existing javascript code in TS
Ambient declarations are done through the “d.ts” files, those files are added to the TS files using the “reference” directive:
/// <reference path = “Calc.d.ts” />
However, d.ts files themselves do not contain any actual implementations – there are only type definitions there:
declare module TutorialPoint {
export class Calc {
doSum(limit:number) : number;
}
}
When it comes to somehow adding actual implementation of the doSum function to your final HTML, you have to it using the script tag:
<script src = “doSumSource.js”></script>