Photo by Raimond Klavins on Unsplash
Typescript 101
If you know Javascript , this is everything you need to get started with Typescript
Table of contents
- Setup
- Primitive types
- Instance Types
- Arrays and Tupes
- Object Types and Type Alias
- Const declarations
- Functions
- Structural Typing
- Classes
- Generics
- Special Types: any and unknown
- React and Typescript
- Type Assertions
- Type Casting
- Modules
- Type Declarations / Declaration Files (.d.ts)
- Express and Typescript
- Creating an npm package
- npx tsc , node lib/index.js
- Async await
- ts-node
- Lexical this
- readonly modifier
- Union Types
- Literal Types
- Type Narrowing
- Discriminated Unions
- Class Parameter Properties
- Strict Compiler Option
- Null vs undefined(runtime absence of value)
- Intersection Types (inheritance in types)
- Optional Modifier
- Non-null Assertion Operator(! after the value which TS believes may be null or undefined)
- Interfaces
- Interface Declaration Merging
- Types(type alias) vs Interfaces
- never type
- implements keyword
- Definitive Assignment Assertion
- User-defined Type Guards
- Assertion Functions (Testing)
- Function Overloading(Compile only)
- Call Signatures
- Abstract Classes
- Index Signatures
- Read -only Arrays and Tuples
- Double Assertion
- Const Assertion
- this parameter
- Generic Constraints
Setup
Primitive types
Instance Types
Arrays and Tupes
- Unlike an array , for a tuple the size is fixed and type is fixed
Object Types and Type Alias
Const declarations
Functions
Structural Typing
Classes
Generics
Special Types: any and unknown
all types can be assigned to any or unknown
the difference is that and can be assigned to a concrete type later and every member access is also referred to be any,so any chaining is possible
unknown can accept anything but you cannot use it in a unsafe manner , you cannot assign it a concrete type not can you access memner variables without explicit type checks
React and Typescript
npx create-react-app react-ts --template typescript
Type Assertions
The ideal way is still runtime checks as assertions just shut up the compiler, the mask the error
Type Casting
Modules
Type Declarations / Declaration Files (.d.ts)
npm i @types/node // as opposed to creating declaration file ourselves
Express and Typescript
Many packages are written in TS, so we can simply install and use them
The same is not true for some other packages like Express, so we need to install their types explictly
Creating an npm package
mkdir palind
cd palind
npm init -y
npm i typescript -D //typescript as a dev dependecy
npx tsc -init
--rootDir src --outDir lib --sourceMap --declaration --declaratinoMap
// we enable sourceMap so we could debug ts from gen. js
// we enable declaration so that compiler generates type definations which can be used by our ts consumers
//we enable declaratinoMap which allows our ts consumers to navigate from the type definations to the source code
we can now simply publish this by `npm publish`
we can consume this package by `npm i palind` and then we can import it like any other module
npx tsc , node lib/index.js
Async await
ts-node
ts cannot be run natively on node ie node src/index.ts would not work , we have to run js after compilation (npx tsc , node lib/index.js)
Instead, if we use ts-node
npm i ts-node npx ts-node src/index.ts
Lexical this
there are two ways to think about 'this' keyword in js , one being the callling context other being the lexical scope
unlike arrow and bound functions, this is driven by calling context
Functions in js are first class, which means if they can be stored in a variable
Arrow functions capture 'this' from the surrounding context, since all property initialisers execute at the end of the constructors,
this
will be bound to whatever instance is present within constructor
readonly modifier
- just like other access modifiers public,private,protected the read only modifier in ts is a compile time only feature used for compile time error checking
Union Types
Literal Types
Type Narrowing
below the instances of Sqare and Rectangle are not constructed by classes we cannot use the JS instanceof operator to differentiate between two objects
Discriminated Unions
Class Parameter Properties
Strict Compiler Option
Null vs undefined(runtime absence of value)
Intersection Types (inheritance in types)
Optional Modifier
Non-null Assertion Operator(! after the value which TS believes may be null or undefined)
- non-null assertions are also compiled time and have no runtime impact
but we must always write code in a way that avoids these assertions
Interfaces
type defined structure of an object, so do the interface
Interface Declaration Merging
An example would be in Express, where interface merging allows us to add additional properties to the request interface via middleware (ex. jsonMiddlerware)
this is NOT supported by type aliases
Types(type alias) vs Interfaces
- generally, achieve the same effect
but since interfaces need to have a body, we cannot create them by using smaller type declarations
only if you NEED interfaces, use them or else use types
never type
used for ensuring logical code correctness
only something of the type never can be assigned to type never
below TS can now infer the type to be `Number`
implements keyword
Definitive Assignment Assertion
typescript does understand the mutating side-effects of a function
- one of the solutions would be to use non-null assertions , the other may to be refactor the code to make this function pure
the third solution is using ! at time of declaration itself
User-defined Type Guards
Earlier to differentiate types we added a common member of different literal types, thus creating a discriminated union
the other solution is using user-defined type guards, they are much more readable
Assertion Functions (Testing)
Function Overloading(Compile only)
Call Signatures
Abstract Classes
Index Signatures
Read -only Arrays and Tuples
Double Assertion
Const Assertion
strings are immutable in JS
converts primitives to literal types and members are readonly
we can even fix this with an explicit type annotation
this parameter
must always be the first parameter if used