1/29
Looks like no tags are added yet.
Name | Mastery | Learn | Test | Matching | Spaced |
---|
No study sessions yet.
Typescript
It's a programming language, with static typing and strong typing (created by Microsoft). TypeScript code is compiled (by tsc) to JavaScript, and can be executed in browsers and Node.js. Easier to maintain code, catch errors. Typescript is installed globally on the computer.
Type annotations vs Type inference
Type annotation - when you specify the type using colon
Type inference - when it automatically determined based on assigned value
unknown
Unknown type is used when we don’t know what type we receive, but before using that variable, we need a type check
Void
Void type is used for defining a function, that doesn't return anything
Tuple
Tuple is an array that contain two(or more) fields of different data types.
var employee: [number, string] = [1, "Steve"];
Union
Union type - when a variable can hold one of several types. It is defined using the vertical line symbol.
let value: string | number = 'hello'; value = 42;
Discriminating union (tagged)
A discriminated union is same as union, but each type has a unique "tag": a specific property, that helps TypeScript identify which type is currently used.
Intersection Type
Intersection Type allows you to combine multiple types into one using (ampersand) & symbol. Resulting type must have all properties and methods from each of the types.
type EmployeeDetails = Person & Employee;
Objects in TypeScript are structurally typed
In a structural type system, types are determined based on their shape (i.e., the properties they have and the types of those properties) rather than their name or identity. This means that TypeScript cares about what properties and methods an object has, not what its type is named.
There is also nominal typing, where types are defined by name, and two types with the same structure may not be equivalent if it’s not explicitly declared.
Utility types
1. Record<K, T>
2. Pick<T, K>
3. Omit<T, K>
4. Required<T>
5. Partial<T>
Readonly
readonly modifier is used to indicate that a property or an array cannot be modified after it is initialized. This provides a read-only behavior in your objects and arrays
Utility types: Record<K, T>
To create an object type with specific keys and values. All keys must be of type X, and all values must be of type X. F.e. object as a keys can have only strings 'admin', 'user', and 'guest', which are listed in type UserRoles.
enum
enum - (short for enumeration) set of related named constants (like colors or statuses). Can consist of strings/numbers/both. Makes your code more organized
But if we don't need computed values in enums we can use const enums (just by adding const keyword before enum), and such const enums will be completely removed during compilation
enum Color {
Red = "#dde310",
Green = "#fefw20",
}
never
never - void type can have undefined or null as a returned value but never cannot have any value.
Utility types: Pick<T, K>
To create a new type by picking specific properties from an existing type. You provide the original type T) and a set of properties K) that you want to include.
Utility types: Omit<T, K>
The opposite of Pick. It creates a new type by removing specific properties from an existing type. You provide the original type T) and the properties K) you want to omit.
Utility types: Required<T>
Makes all properties of a type required.
Utility types: Partial<T>
Makes all properties of a type optional. It’s useful when you want to allow missing properties in an object.
Type Guard
Narrows down the type of a variable within a conditional block.
Function overloading
function greet(name: string): string;
function greet(age: number): number;
function greet(value: string | number): string | number {
if (typeof value === 'string') {
return Hello, ${value};
}
return value * 2;
}
Defining multiple signatures for the same function, with a single implementation.
keyof operator
Returns a union type representing all the keys of an object type
type Person = { name: string; age: number };
let key: keyof Person; // 'name' | 'age'
mapped types
When you want to create new types by transforming properties of an existing type. It maps over an existing type and make changes to its properties. For example, if you want to change each property to be a string, or to be read-only
type Person = {
name: string;
age: number
};
type ReadOnlyPerson = {
readonly [K in keyof Person]: Person[K]
};
type StringifiedPerson = {
[K in keyof Person]: string;
};
Interface vs type keyword
1. *interface**: can only describe objects and classes, *type**: describes also unions, intersections, and primitive types.
2. to extend an interface use the extends keyword, to extend types using intersection &)
3. interface has a declaration merging, If you declare an interface with the same name multiple times, TypeScript will merge them into one. If you declare a type with the same name multiple times, TypeScript will throw an error.
Interfaces vs classes
Interface Describes the structure of an object. Which properties and methods should be in it and theirs types.
Unlike Classes, Interfaces:
- only define the object structure, it doesn't have methods implementation or property initialization (classes have)
- interfaces can inherit other interfaces, but can't inherit classes (classes can)
- can't create new object's instances with a 'new' keyword (with class you can)
- interfaces don't have getters and setters and constructor
Generics
It is a type variable, so it works for several types. It makes the dependency between the argument type and the return type.
Abstract classes
Class which doesn't have an instance, first you need to inherit in and only then have an instance (realization).
Abstract Methods should not have implementation
Usually abstract class is needed to describe something generalized
infer
keyword is used inside conditional types, which are types that change based on a condition. When you use infer, you're telling TS to infer the type based on the structure of the data (take the structure of the data as a template).
type TypeName<T> = T extends SomeType ? InferType : OtherType;
declaration files .d.ts)
It stores function signatures, variables types definitions for ts. JS libraries don't have type information, declaration files .d.ts) provide type information. It doesn't contain the implementation, it just describes types.
Module augmentation
Imagine you're using a library for some task (like a calculator), but you want to add a new function to it. You don’t want to change the library itself, you just want to extend it. You can do this by using module augmentation. To do that use declare module syntax. Is needed for extending Third-Party Libraries
// This is the magic part where we augment the module.
declare module './person' {
// We're adding a new property `address` to the existing Person interface.
interface Person {
address: string;
}
}
Template literal types
Literal type is a specific strings or numbers. Literal types aren’t very valuable if a variable can only have one value, but by combining literals into unions you can specify several strings (f.e) which are acceptable:
alignment: "left" | "right" | "center"
Template literal types build on string literal types, syntax is similar to template literals in JS. They allows to define types by combining pieces of strings. F.e. you want to define a type for various color codes, like #ff0000, #00ff00, or #0000ff:
type ColorCode = `#${string}`;
//The `#` is a fixed part of the string