Quick points on how to use typescript
- Install TS Compiler `npm install -g typescript'
- Initialise the project
tsc --init
- You can run
tsc <file/path>
TS helps to catch errors before runtime unlike JS by doing type checks while coding.
const message = "hello!";
message();
// Error: This expression is not callable. Type 'String' has no call signatures
- Accessing non existing properties
const user = {
name: "Daniel",
age: 26,
};
user.location; // JS returns undefined
// Error: Property 'location' does not exist on type '{ name: string; age: number; }'
- Handling typos
const announcement = "Hello World!";
// How quickly can you spot the typos?
announcement.toLocaleLowercase();
announcement.toLocalLowerCase();
// We probably meant to write this...
announcement.toLocaleLowerCase();
- Uncalled functions
function flipCoin() {
// Meant to be Math.random()
return Math.random < 0.5;
// ERROR: Operator '<' cannot be applied to types '() => number' and 'number'.2365
}
- Logic Errors
const value = Math.random() < 0.5 ? "a" : "b";
if (value !== "a") {
// ...
} else if (value === "b") {
// Error: This condition will always return 'false' since the types '"a"' and '"b"' have no overlap.2367
}
Type inference -> identifying the type of variable
TS by default detects the type hence it is not good practice define the type of variable (at declaration) unless the variable is not assigned with values.
Ex.
-- const num = 5;
--> Define type number:5
-- let num = 5;
--> Define type number
-- let num;
--> Define type as any
--> Instead do let num:number
An interface declaration is another way to name an object type:
interface User {
name: string;
id: number;
}
const user: User = {
name: "Rinku",
id: 131,
};
function getAdminUser(): User {...}
function deleteUser(user: User) {...}
Type aliases and interfaces are very similar, and in many cases you can choose between them freely. Alias type
cannot be re-opened to add new properties vs an interface
which is always extendable. Read More
type LockStates = "locked" | "unlocked";
Generics provide variables to types. An array without generics could contain anything. An array with generics can describe the values that the array contains.
type NumberArray = Array<number>;
type ObjectWithNameArray = Array<{ name: string }>;
Declaring own type
interface Backpack<Type> {
add: (obj: Type) => void;
get: () => Type;
}
declare const backpack: Backpack<string>;
const object = backpack.get(); // --> string
Generic function, Multiple infer & Contraints - function types
In TS, Type checking focuses on the shape that values have. Say, if two objects have the same shape, they are considered to be of the same type.
interface Point {
x: number;
y: number;
}
function logPoint(p: Point) {
console.log(`${p.x}, ${p.y}`);
}
// logs "12, 26"
const point = { x: 12, y: 26 };
logPoint(point);
The point
variable is never declared to be a Point
type. However, TypeScript compares the shape of point
to the shape of Point
in the type-check. They have the same shape, so the code passes.
Here obj: { first: string; last?: string }
last
is optional properties. Which means it can optionally be part of object while passing in params and TS will not throw error.
function printName(obj: { first: string, last?: string }) {
// ...
}
// Both OK
printName({ first: "Bob" });
printName({ first: "Alice", last: "Alisson" });
TypeScript also has a special syntax for removing null and undefined from a type without doing any explicit checking. Writing ! after any expression is effectively a type assertion that the value isn’t null or undefined
function liveDangerously(x?: number | null) {
// No error
console.log(x!.toFixed());
}
it’s important to only use ! when you know that the value can’t be null or undefined.
used for very large integers
const oneHundred: bigint = BigInt(100);
const anotherHundred: bigint = 100n;
There is a primitive in JavaScript used to create a globally unique reference via the function Symbol():
const firstName = Symbol("name");
const secondName = Symbol("name");
if (firstName === secondName) {
// ERROR: This condition will always return 'false' since the types 'typeof firstName' and 'typeof secondName' have no overlap.
// Can't ever happen
}
Limiting the kinds of types that a type parameter can accept.
- https://youtu.be/BwuLxPH8IDs?t=7689
- https://github.com/typescript-cheatsheets/react#reacttypescript-cheatsheets
- https://github.com/typescript-cheatsheets/react-native
- https://reactnative.dev/docs/0.60/typescript
- Call Signatures - describe callable with properties
- Contruct Signatures - Invoking function with
new