For types, we have all our basic types and we can also have custom types.
There are two types, primitive
and object
- the object
types itself can be what we define.
Why do we care? The compiler uses it to search for errors and it allows other engineers to understand what type of data is flowing around.
interface Todo { id: number; completed: boolean; }; const todo = obj.data as Todo;
// array let colors: string[] = ['a', 'b', 'c']; // class class Car {} let car: Car = new Car(); // object literal let point: { x: number, y: number } = { x: 10, y: 20 }; // functions const logNumber: (i: number) => void = (i: number) => { console.log(i); };
The object literal gets a bit nasty, but we have ways around this using types
and interfaces
.
const json = '{"x":10, "y": 20}'; const coordinates = JSON.parse(json); // by default gets any time // this is the better const coor: { x: number, y: number } = JSON.parse(json);
// Returns nothing const logger = (message: string): void => console.log(message); // Never returns const throwError = (message: string): never => throw new Error(message);
interface Vehicle { name: string; year: number; broken: boolean; } const oldCivic = { name: 'civic', year: 2000, broken: true }; const printVehicle = (vehicle: Vehicle): void => {};
Good for classes that we only want to use to extend. Think expectation vs reality.
Abstract classes:
abstract class Examlpe { // promises we will create this func later abstract requireFunc(argA: number): void; swap = (a:number) => requireFunc(a); }
enum Result { Win = 'W', Loss = 'L', Draw = 'D' }
class HoldAnything<TypeOfData> { data: TypeOfData; } const holdNumber = new HolderAnything<number>(); const holdString = new HolderAnything<string>(); interface Coordinates { x: number; y: number; } const holdCoordinates = new HolderAnything<Coordinates>(); // TypeOfData can actually be called anything // Convention is normally T, but then we go alphabetical order if we need multiple generics class holdMultipleAnything<T,U,V> { firstThing: T; secondThing: U; thirdThing: V; } const holdAllTheThings = new holdMultipleAnything<string, number, Coordinates>();
class Car { print() { console.log('Car'); } } class House { print() { console.log('House'); } } interface Printable { print(): void; } function printWhatever<T extends Printable>(el: T) { el.print(); } printWhatever(new Car()); printWhatever(new House());
// what you have to do without method overloading class Utility { static function addNumbers(a:number, b: number): number { return a + b; } static function addStrings(a:string, b: string): string { return a + " " + b; } } Utility.addNumbers(1,2) // return 2 Utility.addStrings('Hello','World') // return "Hello World" // method overloading in other languages class Utility { static function add(a:number, b: number): number { return a + b; } static function add(a:string, b: string): string { return a + " " + b; } } Utility.add(1,2) // return 2 Utility.add('Hello','World') // return "Hello World" // method overloading in other typescript class Utility { static function add(a:number, b: number): number; static function add(a:string, b: string): string; static function add(a, b) { return a + b; } } Utility.add(1,2) // return 2 Utility.add('Hello','World') // return "HelloWorld"