- Typescript Basics
- Type Annotations for variables
- Function anotations
- Object Types
- Union Types
- Type Aliases
- Interface
- Difference between Interface and Type aliases.
- Type Assertions
- Enums
- What is actually Type Narrowing?
- Null and Undefined.
- Function anotations
- Less Common Primitives.
- More On Functions.
- NUMBER
- STRING
- BOOLEAN
- NULL
- UNDEFINED
- VOID (SPECIAL KIND OF TYPE)
- ANY (DANGEROUS)
- NEVER
- UNKNOWN
keywords like const, let, var when we define the variables names with these keywords, we have an option in typescript to add explicitly define type of the variable.
// string
const stringOne: string = "YasirKhan" // Here (: string) is type annotation for variables (stringOne).
// number
const numberOne: number = 99; // Here (: number) is type annotation for variables (numberOne).
// Boolean
const isLoggedIn: boolean = true;
function add(a: string, b: string) { // Here type annotations for function parameter is string.
return a + b;
}
console.log(add("stringOne", "stringTwo")) // stringOnestringTwo
function Add(a: number, b: string) {
return a, b;
}
console.log(Add(10, " stringThree")) // 10 stringThree
function Coordinates(points: {x: number, y: number}) {
console.log(`The co-ordinates of x-axis:`, points.x);
console.log(`The co-oridinates of y-axis:`, points.y);}
Coordinates({x: 34, y: 40})
// The co-ordinates of x-axis:34
// The co-ordinates of y-axis:40
You can also add optional properties to object type.
function user(obj: {name: string, age: number, email?: string, department?: string}) {
console.log(`Hi, My name ${name} I'm ${ age } currently working as a Frontend Developer at Graffitechs in ${department}. You can contact me on this ${email}.`)
}
user({name: "yasir"})
Typescript allow developers to use new types out of existing one.Union type is a type which is formed by two or more other types with the help of the some operator.
// here I represented the possible values by string or number by | operator.
function printID(id: string | number) {
console.log("Here is your id:", id)
}
printID("stringOne") // stringOne
printID(30) // 30
// another example
function printDetails(Id: string[] | number) = {
console.log(id)
}
printDetails(["stringOne", "stringTwo"]) // ["stringOne", "stringTwo"]
function greetings(str: string[] | number) {
if(Array.isArray(str)) {
console.log(`Hello, ${str.join(" and " )}`)
}else {
console.log("welcome lone traveller " + x)
}
}
greeting(["stringOne", "stringTwo"])
greeting(23)
Type Alias is exactly that - a name for any type. In typescript, type aliases give a type a new name.They are similar like interfaces but used to give a new type to primitives. Aliasing doesn't create a new type, but It gives just a new to type. So summary is Just give another name to the type.
type NormalType = string | boolean | number;
const stringValue: NormalType; // assigned type alias for variable stringValue.
stringValue = "stringOne"; // stringOne
const numberValue: NormalType; // assinged type alias for variable numberValue.
numberValue = 99; // 99
const booleanValue: NormalType; // assigned type alias for variable booleanValue.
booleanValue = false; // false
type functionTypes = number | string;
let variable: string
function displayId(id: functionTypes) {
if(typeof id === typeof variable) {
console.log(`This is my secret ID: ${id}`)
}else {
console.log(`here is my ID ${id.toString()}`)
}
}
displayId("2345E3")
displayId(233221)
- Interface is used to define the structure of objects and functions same as type aliases.
- In typescript, It is like we are using type aliases here, matter of fact is that it act like we are using an anonymous object here.Typescript only cares about the structure of the values pass to them.
- If the structure of the functions and objects, then it will generate onspot compile time errors.
interface User {
name: string;
age: number:
email: string
}
const userOne: User = {
name: "yasir",
age: 22,
email: "abc@gmail.com"
}
console.log(userOne)
interface keyValuePair { (key: number, value: string): void; }
function addKeyValue(key: number, value: string): void {
console.log("addkey: key = " + key + " value = " + value)
}
function updateKeyValue(key: number, value: string): void {
console.log("updateKey: key = " + key + " value = " + value)
}
let keyValueOne: keyValuePair = addKeyValue;
let keyValueTwo: keyValuePair = updateKeyValue;
keyValueOne(33, "Mohammad Bin Qasim.")
keyValueTwo(23, "Billy Bowdan")
interface numList {[index: number]: number}
let numberArray: numList = [22, 23, 24];
console.log(numberArray[0]) // 22
console.log(numberArray[1]) // 23
console.log(numberArray[2]) // 24
interface stringlist {[index: string]: string}
let stringString: stringList ={};
console.log(stringOne["JS"] = "Javascript") // Javascript
console.log(stringTwo["TS"] = "Typescript") // Typescript
We can have optional properties ? in interface objects. In such Cases, the objects of the interface will not define these properties.
interface Employee {
empId: number,
empName: string,
empDepart?: string // ? optional property
}
const employeeOne: Employee = {
empId: 2,
empName: "Imran"
}
const employeeTwo: Employee = {
empId: 3,
empName: "Saluddin",
empDepart: "Finance Department"
}
console.log(employeeOne) // ok
console.log(employeeTwo) // ok
Interfaces can be extended to one or more interfaces. This makes interfaces more flexible or reusable.
interface Person {
name: string;
gender: string;
}
interface Employee extends Person {
status: string; // ok
}
// person
let person: Employee = {
name: "string";
gender: "Male";
status: "Ok"
}
Interface | Type |
---|---|
An interface declaration always introduces a named object type. | A type alias declaration can introduce a name for any kind of type, including primitive, union, and intersection types. |
An interface can be named in an extends or implements clause. | Type alias for an object type literal cannot be named in an |
Interfaces create a new name that is used everywhere. | Type aliases don't create a new name. |
An interface can have multiple merged declarations. | Type alias for an object type literal cannot have multiple merged declarations. |
It uses the "interface " keyword for declaring an interface that can contain the methods, properties, and events to describe data shapes. | It uses the "type" keyword for creating new type alias not a new type instead of a new name for a type defined. |
Interface supports the use of the object. | The type aliases supports only the data types and not the use of an object. |
Interface keyword when used for declaring two interfaces with the same name has the capability to merge these two interfaces. | Type keyword when used for declaring two different types where the variable names declared are same then the typescript compiler will throw an error. |
The interface cannot be used with other types declaration as done with type in typescript. | the types can be used for other types also such as primitives, unions and tuples. |
The interfaces can be extended withthe type alias or interface can be extended by type also. where interface can easily extend classes is one of the best features of the typescript interface. | In typescript type, or type aliases cannot be extended and hence the type cannot extend class as it does not support this feature. |
In typescript, we cannot create any new intersection interface by combining different types as it does not work in typescript. | In typescript, we can create an intersection type by combining multiple types into a single type and can also create a new intersection type by combining two interfaces using the "&" keyword. |
Interfaces are most recommended for defining a new objects or method or property of an object where it will receive a specific component. hence interface works better when using objects and method objects. Therefore it is our choice to choose between types or interface according to the program needs. | Types are better used when we create a function which will return an object when the function is called. hence they are more recommended when using functions, complex types, etc. Therefore it left to us to decide what to be used in our programs. |
The interface cannot support this feature as we cannot create a union interface by combining two types. In typescript, interface cannot support the declaration of tuples as it can be done using types. Therefore the interfaces of typescript do not support the computed properties. | In Typescript, union types can contain one or more types using the " |
In Typescript, the interface supports the feature of implementation where it can implement the objects or members of the class from the derived classes. | In type aliases, type again does not support the feature of implemention where it is only for declaring variables as they cannot implement other types. |
- Type assertions in typescript is a technique to tells the compiler not the infer the TYPE of the variable.The compiler on its own infer the type of the variable. By doing type assertions we can prevent it.
- If we want to change the variable from one type to another such as any to number etc, then we use type assertion.
- We can use angle brackets <> or either as keyword to do type assertions. The as keyword is recommended other then <> because in JSX it will create ambiguity.
var foo = {};
foo.bar = 123; // Error: property 'bar' does not exist on `{}`
foo.bas = 'hello'; // Error: property 'bas' does not exist on `{}`
Here the code errors because the inferred type of foo
is {}
i.e. an object with zero properties. Therefore you are not allowed to add bar or bas to it. You can fix this simply by a type assertion as Foo
:
We may sometimes encounter a circumstance in which we will defined an object without any initial values, properties. In such cases, the compiler will throw an error. However, We can prevent this by applying type assertions for objects.
let person = {};
person.name = "yasir" // Compiler Error: property name does not exist on type {}.
person.role = "ux designer" // Compiler Error: property role does not exist on type {}.
interface Person {
name: string
role: string
}
let employee = <Person> {};
employee.name = "yasir" // ok
employee.role = "ux designer" // ok
- Enums also known as enumerations, added into Javascript by Typescript.
- Enums allow use to use and declare a set of named constants i,e that can be numeric or string.
- There are three types of enums
- Numeric Enum
- String Enum
- Heterogeneous Enum
- Numberic enum store string values as number. Numeric enums are alwasy number based enums.
enum SocialMedia {
Facebook,
Twitter,
Instagram,
Linkedin,
} // ok
- In the above example,
SocialMedia
enum the initial member starts from value0
and incremented to each member by1
. You just not only assign seqential values. These enums can have any values.Yeah
enum SocialMedia {
Facebook = 20,
Twitter = 30,
Instagram = 5,
LinkedIn = 24
} // ok
- The difference is that string enum store
string values
rather than numeric values. - String enum offer better
readability
if we have to debug a program then it will be easier toread
string values as compared to numeric values.
enum PrintMeida {
Jang = "Jang",
Express = "Express",
Dawn = "Dawn",
Tribune = "Tribune"
} // string enum initialized with string values.
- Type narrowing is actually a narrow down a general type to more specific and precise one.
- Type narrowing is basically
reducing
the type ofvariable
orexpression
based on the surronding text. - This will allow to be more type specific information to be
inferred
atcompile time
, imporving the overalltype checking
of the code.
let x: number | string;
x = 34;
if(typeOf x === "number") {
console.log(x.toFixed(2)) // ok
x = "Hello"; // x is now string.
}
console.log(x.toFixed(2)) // error: methods of type number are not assignable to type string.
The instanceOf
operator is used to narrow down the object type to a more specific class of interface type.
interface Shape {
draw(): void;
}
class Circle implements Shape {
draw() {
console.log("Drawing Circle")
}
}
class Square implements Shape {
draw() {
console.log("Drawing Square")
}
}
function drawShape(shape: Shape) {
if(shape instanceOf Circle) {
shape.draw(); // Drawing Circle
}
}
drawShape(new Circle()) // ok => Drawing Circle.
drawShape(new Square()) // No result/output.
The Null and undefined types can be used to narrow a union type to a non-null
or non-undefined
type.
let y: string | null;
y = 'stringOne';
if(y !== null) {
console.log(y.toUpperCase()) // ok
y = null;
}
console.log(y.toUpperCase()) // Error: y is now possibly null.
-
Javascript has two primitives values for signaling absent, uninitalized or empty values: which is
null
andUndefined
. -
typescript also provide same type of these values but they are depend on the fact that in
tsconfig.json
thestrickNullChecks
option is enabled or not. -
when
strictNullChecks
is off, the compiler will not check the fornull
andundefined
values, which will eventually lead to more bugs and exceptions. So it's alwasy recommended,strictNullChecks
option should be enabled.
function doSomethingHere(x: string | null) {
if(x === null) {
console.log("If true log the value:", x)
} else {
console.log(x.toUpperCase());
}
}
doSomethingHere("stringOne") // STRINONE
Apart from string
, number
, boolean
, null
and undefined
. There are less common primitives also in javavscript, which is bigInt
and Symbol
.
- BigInt in javavascript is used to represent the very large integers. In typescript, you can get
BigInt
by calling the functionBigInit()
or writing biginit literal by adding ann
to the end. - Note: make sure to change the compiler option to
es2020 or later
in tsconfig.json.
let integer__One: bigint = BigInt(100); // with function.
let integer__two: bigint = 100n; // with literal.
console.log(integer__One) // 100
console.log(integer__two) // 100
- Symbol is javascript primitive which is used to create unique global reference via function.
- Symbols are unique and immutable.
const firstName = Symbol("yasir");
const lastName = Symbol("khan");
if(firstName === lastName) {
console.log("This condition will return error.") // error
}
- Funcitons are building-block of any programming language.But in javascript, it's more significant.
- Functional programming in Javascript is used to implement the concepts of object oriented programming like classes, objects, abstraction, and polymorphism etc.
- The function which is declare and and called by it's name.
function displayuserName() {
console.log("Hello typescript")
}
displayuserName(); // output: Hello typescript
- Anonymous Functions are defined as an expression and further stored in a variable.
- The type of function which does not have a name but rather these are stored in a variable.
- These Functions are invoked by calling the name of the variable.
let variableOne = function() { // function expression.
console.log("This function supposed to return the string.")
}
variableOne(); // output: This function supposed to return the string.
- In javascript, functions are first-class citizens because you can treat them as like any other object. You can assign them to a variable, you can return them from anothe function, you can assign them to another function, also you can assign them to another object, you can assign them properties and read back those propperties etc.
- When you don't want to use function arguments use call signatures.
- In Javascript, you can invoke the function the with the
new
keyword (also called aconstructor function
). - In typescript, you can define those kinds of functions using the construct signature.
- example goes here.
-
It’s common to write a function where the types of the input relate to the type of the output, or where the types of two inputs are related in some way.
-
Generics appears in typescript code inside angle brackets, in the format of
<T>
. -
Take a look at following example:
function authentication(auth) {
return auth;
}
// You can make type-safe in typescript like this:
function authentication<T>(auth: T): T {
return auth;
}
const result = authentication(123) // ok