Skip to content

Instantly share code, notes, and snippets.

@renso3x
Forked from dimitardanailov/01: basic types.ts
Created November 21, 2019 03:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save renso3x/9837170859254a7e6f651a210c1e63e9 to your computer and use it in GitHub Desktop.
Save renso3x/9837170859254a7e6f651a210c1e63e9 to your computer and use it in GitHub Desktop.
Typescript in action
/**
* Boolean
*
* The most basic datatype is the simple true/false value,
* which JavaScript and TypeScript (as well as other languages) call a 'boolean' value.
*/
var isDone: boolean = false;
/**
* Number
*
* As in JavaScript, all numbers in TypeScript are floating point values.
* These floating point numbers get the type 'number'.
*/
var height: number = 6;
/**
* String
*
* Another fundamental part of creating programs in JavaScript for webpages and servers alike is working with textual data. As in other languages, we use the type 'string' to refer to these textual datatypes. Just like JavaScript,
* TypeScript also uses the double quote (") or single quote (') to surround string data.
*/
var name: string = "bob";
name = 'smith';
/**
* Array
*
* TypeScript, like JavaScript, allows you to work with arrays of values. Array types can be written in one of two ways.
* In the first, you use the type of the elements followed by '[]' to denote an array of that element type:
*/
var list:number[] = [1, 2, 3];
// The second way uses a generic array type, Array<elemType>:
var list:Array<number> = [1, 2, 3];
/**
* Any
*
* We may need to describe the type of variables that we may not know when we are writing the application.
* These values may come from dynamic content, eg from the user or 3rd party library. In these cases, we want to opt-out of type-checking and let the values pass through compile-time checks. To do so, we label these with the 'any' type:
*/
var notSure: any = 4;
notSure = "maybe a string instead";
notSure = false; // okay, definitely a boolean
// Our First Interface
// The easiest way to see how interfaces work is to start with a simple example:
function printLabel(labelledObj: {label: string}) {
console.log(labelledObj.label);
}
var myObj = {size: 10, label: "Size 10 Object"};
printLabel(myObj);
// We can write the same example again,
// this time using an interface to describe the requirement of having the 'label' property that is a string:
interface LabelledValue {
label: string;
}
function printLabel(labelledObj: LabelledValue) {
console.log(labelledObj.label);
}
var myObj = {size: 10, label: "Size 10 Object"};
printLabel(myObj);
/**
* Traditional JavaScript focuses on functions and prototype-based
* inheritance as the basic means of building up reusable components,
* but this may feel a bit awkward to programmers more comfortable
* with an object-oriented approach, where classes inherit functionality
* and objects are built from these classes. Starting with ECMAScript 6,
* the next version of JavaScript, JavaScript programmers will be able to build their applications
* using this object-oriented class-based approach. In TypeScript, we allow developers to use these techniques now,
* and compile them down to JavaScript that works across all major browsers and platforms, without having
* to wait for the next version of JavaScript.
*/
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
var greeter = new Greeter("world");
// Implementing an interface
// One of the most common uses of interfaces in languages like C# and Java,
// that of explicitly enforcing that a class meets a particular contract, is also possible in TypeScript.
interface ClockInterface {
currentTime: Date;
setTime(d: Date);
}
class Clock implements ClockInterface {
currentTime: Date;
setTime(d: Date) {
this.currentTime = d;
}
constructor(h: number, m: number) { }
}
// TypeScript supports getters/setters as a way of intercepting accesses to
// a member of an object. This gives you a way of having finer-grained control
// over how a member is accessed on each object.
var passcode = "secret passcode";
class Employee {
private _fullName: string;
get fullName(): string {
return this._fullName;
}
set fullName(newName: string) {
if (passcode && passcode == "secret passcode") {
this._fullName = newName;
}
else {
alert("Error: Unauthorized update of employee!");
}
}
}
var employee = new Employee();
employee.fullName = "Bob Smith";
if (employee.fullName) {
alert(employee.fullName);
}
/**
* Up to this point, we've only talked about the instance members of the class,
* those that show up on the object when its instantiated. We can also create static members of a class,
* those that are visible on the class itself rather than on the instances. In this example, we use 'static' on the origin,
* as it's a general value for all grids. Each instance accesses this value through prepending the name of the class.
* Similarly to prepending 'this.' in front of instance accesses, here we prepend 'Grid.' in front of static accesses.
*/
class Grid {
static origin = {x: 0, y: 0};
calculateDistanceFromOrigin(point: {x: number; y: number;}) {
var xDist = (point.x - Grid.origin.x);
var yDist = (point.y - Grid.origin.y);
return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale;
}
constructor (public scale: number) { }
}
var grid1 = new Grid(1.0); // 1x scale
var grid2 = new Grid(5.0); // 5x scale
alert(grid1.calculateDistanceFromOrigin({x: 10, y: 10}));
alert(grid2.calculateDistanceFromOrigin({x: 10, y: 10}));
/**
* In JavaScript, every parameter is considered optional, and users may leave them off as they see fit.
* When they do, they're assumed to be undefined. We can get this functionality in TypeScript by using the '?'
* beside parameters we want optional. For example, let's say we want the last name to be optional:
*/
function buildName(firstName: string, lastName?: string) {
if (lastName)
return firstName + " " + lastName;
else
return firstName;
}
var result1 = buildName("Bob"); //works correctly now
var result2 = buildName("Bob", "Adams", "Sr."); //error, too many parameters
var result3 = buildName("Bob", "Adams"); //ah, just right
// Optional parameters must follow required parameters.
// Had we wanted to make the first name optional rather than the last name,
// we would need to change the order of parameters in the function, putting the first name last in the list.
// In TypeScript, we can also set up a value that an optional parameter will have if the user does not provide one.
// These are called default parameters. Let's take the previous example and default the last name to "Smith".
function buildName(firstName: string, lastName = "Smith") {
return firstName + " " + lastName;
}
var result1 = buildName("Bob"); //works correctly now, also
var result2 = buildName("Bob", "Adams", "Sr."); //error, too many parameters
var result3 = buildName("Bob", "Adams"); //ah, just right
/**
* A generic class has a similar shape to a generic interface.
* Generic classes have a generic type parameter list in angle brackets (<>) following the name of the class.
*/
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
}
var myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };
function sortByName(array) {
var result = array.slice(0);
result.sort(function (x, y) {
return x.name.localCompare(y.name);
});
return result;
}
sortByName(5);
interface Person {
name: string;
age: number;
}
function sortByName(array: Person[]) {
var result = array.slice(0);
result.sort(function (x, y) {
return x.name.localCompare(y.name);
});
return result;
}
sortByName(5);
interface Person {
name: string;
age: number;
}
function sortByName(array: Person[]) {
var result = array.slice(0);
result.sort((x, y) => {
return x.name.localeCompare(y.name);
});
return result;
}
sortByName(5);
/**
* Methods within an abstract class that are marked as abstract do not contain an implementation and must be
* implemented in derived classes. Abstract methods share a similar syntax to interface methods. Both define the signature
* of a method without including a method body. However, abstract methods must include the abstract keyword and
* may optionally include access modifiers.
*/
abstract class Department {
constructor(public name: string) {
}
printName(): void {
console.log("Department name: " + this.name);
}
abstract printMeeting(): void; // must be implemented in derived classes
}
class AccountingDepartment extends Department {
constructor() {
super("Accounting and Auditing"); // constructors in derived classes must call super()
}
printMeeting(): void {
console.log("The Accounting Department meets each Monday at 10am.");
}
generateReports(): void {
console.log("Generating accounting reports...");
}
}
let department: Department; // ok to create a reference to an abstract type
department = new Department(); // error: cannot create an instance of an abstract class
department = new AccountingDepartment(); // ok to create and assign a non-abstract subclass
department.printName();
department.printMeeting();
department.generateReports(); // error: method doesn't exist on declared abstract type
function countLines(text?: string[]): number {
let count: number;
for (const line of text) {
if (line.length !== 0) {
count = count + 1
}
}
return count;
}
let a = countLines(["one", "two", "", "three"]);
let b = countLines(["one", "two", null, "three"]);
let c = countLines();
function countLines(text?: (string | null)[]): number {
if (!text) {
return 0;
}
let count = 0;
for (const line of text) {
if (line && line.length !== 0) {
count = count + 1
}
}
return count;
}
let a = countLines(["one", "two", "", "three"]);
let b = countLines(["one", "two", null, "three"]);
let c = countLines();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment