Types

Concepts

Type assignability

We say that type A is assignable to type B if you can use a value of type A in all places where a value of type B is required. For example:

  • assigning a value to a variable
  • passing a function argument
  • returning a value from a function that has an explicit return type

Optionality

consider that by default, null and undefined are part of the domain (Private) of virtually every type. That is, a string can be null, an object property can be null, and so on. When we enable strict null checking, we are removing null from the domains of these types

  • strictNullChecks forces you to explicitly distinguish between values that can be null or undefined and those that cannot be.

we could explicitly extend the type to once again include null as part of the type's domain:

function bar(person: Person | null) {

But this may not be preferable. Instead we can use optional params (in functions and interfaces) to determine if something can be optional or not:

  • also beneficial to use optional chaining to achieve the effect of optionality, (spec:)as opposed to type guards
interface Person {}

function hello(person?: Person) {}

interface Employee {
  id: number;
  name: string;
  supervisorId?: number;
}

hello();
const employee: Employee = {
  id: 1,
  name: 'John',
};
/* * * * */
interface Person { hello(): void }

function sayHello(person: Person | undefined) {
  person.hello(); // 🔴 Error!

    // this is a type guard, and it allows the Typescript Type checker to 
    // deduce that the type of person inside the if statement is narrowed to just `Person`
    if (person) {
        person.hello(); // OK
    }
}

Consider that a getUser function might not return a user for a given ID. Therefore, we should set the return value of the function as a union between User and undefined.

getUser(id: number): User | undefined {
  return this.users[id];
}

spec: If we don't want to specify a new type, we can just do this:

type TodoPrevious = Pick<Todo, "title" | "completed">

Here, "title" | "completed" resolves to a type. We could have written it like this:

type ValueKeys = "tite" | "completed"
type TodoPrevious = Pick<Todo, ValueKeys>

after awaiting that action, the API call to the server is made along with the changelog objects. This should not block the client. if there is a connection to the server, the server will handle it and notify the client. If there is no connection to the server (or simply if there is an error), then the client will keep track of the changelog objects in its own database. Then, once connection to the server is reestablished, the client will send its changelog objects, as per the usual protocol.


Backlinks