What it does:
- randomly generate user
- randomly generate company
It will then show it on google map.
npm install -g parcel-bundler
mkdir RandomGenerate
cd RandomGenerate
touch index.html
mkdir src
cd src
touch index.ts
What it does:
It will then show it on google map.
npm install -g parcel-bundler
mkdir RandomGenerate
cd RandomGenerate
touch index.html
mkdir src
cd src
touch index.ts
1 2 3 4 5 6 7 8 |
class Vehicle { constructor(public color: string) { } protected honk(): void { console.log('beep'); } } |
If we were to construct our Car, we need to make sure it call the parent class’s constructor. We do this by using super, and passing in whatever required parameters is required. In our case, it is color: string.
We then declare new property wheels for Car.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
class Car extends Vehicle { // whenever instance is created, the constructor in parent is being called automatically constructor(public wheels: number, color: string) { super(color); } private drive(): void { console.log('vroooom'); } startDrivingProcess(): void { this.honk(); this.drive(); console.log('this ' + this.color + ' car drove away'); } } const car = new Car(3, 'black'); car.startDrivingProcess(); |
Lastly, make sure we put in the required constructor params for Car when we instantiate it.
Typed Arrays – Arrays where each element is some consistent type of value.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
const carMakers: string [] = ['ford', 'toyota', 'chevy']; const dates = [new Date(), new Date()]; const carsByMake: string[][] = [ ['f150', 'f151'], ['corolla'], ]; // Help with inference with extracting values const car = carMakers[0]; const myCar = carMakers.pop(); carMakers.map((car: string) : string => { return car.toUpperCase(); }); |
1 2 3 4 |
// Flexible types const importantDates = [new Date(), '2030-10-10']; importantDates.push('2030-10-10'); importantDates.push(new Date()); |
When we want to represent a collection of records which some arbitrary sort order.
of same type.
https://stackoverflow.com/questions/49047886/whats-difference-between-array-and-tuple/49047969
Tuple – A tuple is a grouping of unnamed, ordered values. Each value in a tuple does not need to be the same type.
Array An array is mutable collection. They are very efficient to create, but must always be a single type.
We have a literal object like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
const drink = { color: 'brown', carbonated: true, sugar: 40 } // array of string | number | boolean const pepsi = ['brown', true, 40]; // But we have to memorize that 1st is the color, 2nd is boolean, 3rd is number // so we can't use array // we use tuple const pepsi: [string, boolean, number] = ['brown', true, 40]; // that way we get compile time checking // pepsi[0] = 40; would give compile time error |
1 2 3 4 5 |
type Drink = [string, boolean, number]; // create a tuple type const MountainDew: Drink = ['yellow', true, 20]; const sprite: Drink = ['clear', true, 40]; const tea: Drink = ['brown', false, 0]; |
Here’s why we don’t really use it too much.
1 |
const carSpecs: [number, number] = [400, 33543]; |
It does not describe what those numbers mean. It is not descriptive.
Let’s use object instead. It is much more descriptive because we are forced to put in a key.
1 2 3 4 |
const carStats = { horsepower: 400, weight: 3354 } |
Type annotations for functions – Code we add to tell Typescript what type of arguments a function will receive and what type of values it will return.
Type inference for functions – TS tries to figure out what type of value a function will return.
1 2 3 |
const add = (a: number, b: number): number => { return a + b; }; |
1 2 3 |
const subtract = (a:number, b:number): number => { return a - b; } |
Annotate a by providing type number
Annotate b by providing type number
Annotate the return value by providing type number
1 2 3 4 5 6 7 |
function divide(a: number, b: number): number { return a / b; } const multiply = function(a: number, b: number) : number { return a * b; } |
if no return value, we can specify void
1 2 3 |
const logger = (message: string): void => { console.log(message); } |
TypeScript introduced a new type never, which indicates the values that will never occur.
1 2 3 4 5 6 7 8 9 10 11 |
const throwError = (message: string): never => { if (!message) throw new Error(message); return message; } // or function keepProcessing(): never { while (true) { console.log('I always does something and never ends.') } } |
Difference between never and void
ref – https://www.tutorialsteacher.com/typescript/typescript-never
The void type can have undefined or null as a value where as never cannot have any value.
1 2 |
let something: void = null; // ok let nothing: never = null; // Error: Type 'null' is not assignable to type 'never' |
A function that has return type void, and no return value, actually defaults to return undefined.
1 2 3 |
function sayHi(): void { console.log('Hi!') } |
If you you use never type, then sayHi will give a compile time error, as void is not assignable to never.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
const todayWeather = { date: new Date(), weather: 'sunny' }; // parameter is forecast object // return type is void const logWeather = (forecast: { date: Date, weather: string }): void => { console.log(forecast.date); console.log(forecast.weather); } logWeather(todaysWeather); |
In order to do parameter destructuring, we do this:
1 2 3 |
const logWeather = ({ date, weather } : {date: Date, weather: string}): void => { // use date, weather as so } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
const profile = { name: 'alex', age: 20, coords: { lat: 0, lng: 15 }, setAge(age: number): void { this.age = age; } }; // if we want to use de-structuring, we need to write out the structure // { age: number } is the type const { age } : { age: number } = profile; //de-structure out coordinates const { coords: { lat, lng } } : { coords: { lat: number, lng: number } } = profile; |
variable declaration: const color
variable initialization: ‘red’
1 |
const color = 'red'; |
If declaration and initialization are on the same line, Typescript will figure out the type of ‘color’ for us.
If typescript can figure it out, why would we want to do it yourselves?
Try to use Type Inference.
But there are THREE scenarios where we rely on Type Annotations to help Typescript out.
Whenever a function return the any type.
1 2 3 4 5 6 7 8 9 |
// when to use annotations? // 1) function that returns the 'any' type const json = '{"x":10, "y": 20}'; // mouse over coordinates. You'll see 'Any' // mouse over parse and you'll see that the parse function returns // 'any'. const coordinates = JSON.parse(json); |
JSON.parse() –> ‘false’ –> boolean
JSON.parse() –> ‘4’ –> number
JSON.parse() –> ‘{“value”, 5}’ –> {value:number}
Can’t predict what we get in return.
So as a shortcut, typescript uses ‘Any’ type.
We have no idea what type gets returned.
type Any – means TS has no idea what this is – can’t check for correct property references
Avoid variables with ‘any’ at all costs.
The reason why is because say we have declare speed to be string:
1 |
let speed: string = 'fast'; |
if we then go
1 |
speed.abcdef |
TS will let us know that property abcdef does not exist. Because TS knows that speed is a string.
But with Any, TS doesn’t know, and won’t be able to do this check for you.
We can add type annotation for object.
Say we’re expecting an object where there’s a x and y property of type number.
1 |
const coordinates: { x: number, y: number } = JSON.parse(); |
Now if we mouse over coordinates, or try to access a weird random property, we’ll get proper feedback or error.
Another way to add type annotation manually…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// 2) When we declare a variable on oneline // and initialize it later let words = ['red', 'green', 'blue']; let foundWord: boolean; // add annotation of 'boolean' // you can also initialize it like so: // let foundWorld = false; // TS will now know that foundWord is of type false for (let i = 0; i < words.length; i++) { if (words[i] === 'green') { foundWord = true; } } |
1 2 3 4 5 6 7 8 9 10 |
let numbers = [-10, -1, 12]; let numberAboveZero = false; // by default false // However! if number is above zero, we want it to be assigned a number! for (let i = 0; i < numbers.length; i++) { if (numbers[i] > 0) { numberAboveZero = numbers[i]; // type inference would give error here due to default false } } |
what we could do:
1 2 3 4 5 6 7 8 9 10 |
let numbers = [-10, -1, 12]; let numberAboveZero: boolean | number = false; // However! if number is above zero, we want it to be assigned a number! for (let i = 0; i < numbers.length; i++) { if (numbers[i] > 0) { numberAboveZero = numbers[i]; // now this would be ok } } |
1 2 3 |
npm init tsc --init npm install --save-dev webpack webpack-cli webpack-dev-server typescript ts-loader |
Webpack is a tool that allows us to bundle our code. Transform our typescript code into javascript, then emit 1 javascript bundle file.
Webpack-dev-server is a development server.
go to tsconfig file.
“target”: “es6”
“module”:”2016″
touch webpack.config.js
webpack will automatically look for this file.
ref – https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/
process.nextTick() vs setImmediate()
We have two calls that are similar as far as users are concerned, but their names are confusing.
process.nextTick() fires immediately on the same phase
setImmediate() fires on the following iteration or ‘tick’ of the event loop
In essence, the names should be swapped. process.nextTick() fires more immediately than setImmediate(), but this is an artifact of the past which is unlikely to change. Making this switch would break a large percentage of the packages on npm. Every day more new modules are being added, which means every day we wait, more potential breakages occur. While they are confusing, the names themselves won’t change.
We recommend developers use setImmediate() in all cases because it’s easier to reason about.
ref – https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
const user = { id: 42, displayName: 'jdoe', fullName: { firstName: 'John', lastName: 'Doe' } }; function userId({id}) { return id; } function whois({displayName, fullName: {firstName: name}}) { return `${displayName} is ${name}`; } console.log(userId(user)); // 42 console.log(whois(user)); // "jdoe is John" |
ref – https://www.tutorialspoint.com/mongodb/mongodb_create_database.htm
MongoDB’s
use some DB name is used to create database. The command will create a new database if it doesn’t exist, otherwise it will return the existing database.
1 2 |
>use portfolio switched to db portfolio |
However, you must have at least 1 document in your DB before it shows up in the list. So we create one collection and insert 1 document in order for the DB to exist.
1 |
db.transfers.insert({"money", "$1000"}) |
WriteResult({ “nInserted” : 1 })
show dbs
and you’ll see database portfolio listed.
https://www.npmjs.com/package/kafka-node
kafka-node-hello-world
We first require kafkajs module and extract the class. We then create a topic and group ID.
It is simply to identify the group that will be consuming, and the name of a topic that we’ll be producing.
1 2 3 |
const { Kafka } = require('kafkajs') const topicName = "test-topic22" const GroupID = "test-group22" |
Then we instantiate it with a unique client id. For brokers let’s use localhost:9092 because that is what we’re using in our Kafka settings file.
1 2 3 4 |
const kafka = new Kafka({ clientId: 'my8app', brokers: ['localhost:9092', 'localhost:9092'] }) |
get a producer
1 |
const producer = kafka.producer() |
get a consumer
1 |
const consumer = kafka.consumer({ groupId: GroupID }) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
server.route({ method: 'GET', path: '/consumer-subscribe', handler: async (request, h) => { console.log("consumer connect") await consumer.connect() console.log("consumer subscribe") await consumer.subscribe({ topic: topicName, fromBeginning: true }) return true } }); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
server.route({ method: 'GET', path: '/consumer-run', handler: async (request, h) => { console.log("consumer run") await consumer.run({ eachMessage: async ({ topic, partition, message }) => { console.log({ partition, offset: message.offset, value: message.value.toString(), }) }, }) return true } }); |
1 2 3 4 5 6 7 8 9 |
server.route({ method: 'GET', path: '/consumer-unsubscribe', handler: async (request, h) => { console.log("consumer disconnect") await consumer.disconnect({ topic: topicName }) return true } }); |
1 2 3 4 5 6 7 8 9 |
server.route({ method: 'GET', path: '/producer-start', handler: async (request, h) => { console.log('producer connected') await producer.connect(); return true; } }); |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
server.route({ method: 'GET', path: '/producer-send', handler: async (request, h) => { console.log('producer send') return await producer.send({ topic: topicName, messages: [ { value: '8 - Herro KafkaJS user!' }, ], }) } }); |
1 2 3 4 5 6 7 8 9 |
server.route({ method: 'GET', path: '/producer-stop', handler: async (request, h) => { console.log('producer stop') await producer.disconnect() return true } }); |