interface, type, конструкция as

type

type - Это ключевое слово для вынесения псевдонимов типов отдельно от перменных функций и так далее. Вот функция из урока по базовым типам.

function sum(a: number[] | number) {
  // у нас есть union тип
  if (Array.isArray(a)) {
    let num = a.reduce((sum: number, current: number) => {
      // здесь не нужно указывать тип, так как мы  в любом случае можем получить только number
      return sum + current;
    });
    return num;
  } else {
    return a;
  }
}

Так вот с помощью type мы можем наши типы вынести отдельно.

type Calc = number[] | number; // создали псевдоним для типов

function sum(a: Calc) {
  // указали тут и все
  if (Array.isArray(a)) {
    let num = a.reduce((sum, current) => {
      return sum + current;
    });
    return num;
  } else {
    return a;
  }
}

Можно создать объект с типами.

type Point = {
  // представление нашего будущего объекта.
  x: number;
  y: number;
};
function print(coord: Point): string {
  // функция ждет, что получит, объект типа Point
  return `x:${coord.x}, y:${coord.y}`;
}

// мы передаем объект с x и y. То чего от нас и ждали!
console.log(print({ x: 10, y: 11 })); // x:10, y:11

interface

Аналогично работают и интерфейсы.

interface IPoint {
  x: number,
  y: number
}

interface Calc = number | number;

function print(coord: IPoint): string {
  return `x:${coord.x}, y:${coord.y}`;
}

console.log(print({ x: 10, y: 11 })); // x:10, y:11

Так зачем нам и interface и type? В ts рекомендуется использовать interface. Когда же полезен type?
В таких случаях как в первом примере:type Calc = number[] | number;. Когда нам нужно или то или то, без всяких заморочек.

Отличия interface и type

Первое отличие это extends.

interface IPoint extends IPoint3D { // указываем, что наследуем все от IPoint3D
    x: number,
    y: number
//  z:number - по сути теперь у нас тут и z
  }

interface IPoint3D { // Создаем новый интерфейс с z
    z?: number; // сделаем его необязательным
}
  
  function print(coord: IPoint): string { 
    return `x:${coord.x}, y:${coord.y}`;
  }
  
  console.log(print({ x: 10, y: 11, z:1 })); // x:10, y:11, z:1

В type было бы чуть по другому.

type Point = Zpoint & { // указываем, что Point принимает Zpoint и x,y используем &
    x:number,
    y:number
}

type Zpoint = {
    z?:number; // сделаем необязательным
};
  
  function print(coord: Point): string { 
    return `x:${coord.x}, y:${coord.y} ${(coord.z ? `z:${coord.z}`: '')}`; 
    // небольшое условие, если есть z - укажем, нет, то и нечего указывать.
  }
  
  console.log(print({ x: 10, y: 11,z:1})); // x:10, y:11, z:1

А вот что недоступно type это добавление свойств.

interface ITest { // допустим есть у нас такой интерфейс
    name: string
  }
  
  // где то в другом месте мы можем опять его объявить
  interface ITest { 
    surname:string // только тут уже будет surname
  }
  
  function hiDima(myName:ITest):string { // указываем ITest
  return `Hello ${myName.name} ${myName.surname}`
  }

  // получаем строку hello Dima Chernomashentsev
  console.log(hiDima({name:'Dima',surname:'Chernomashentsev'}));
  

Мы объявили два одинаковых interface и они как бы объеденились. Если мы сделаем так с type, то будет ошибка.

as

С помощью as мы можем преобразовать типы. as значит как! Мы говорим что-то вроде, как вот это!

interface IPoint {
  x:number,
  y:number
}


interface I3DPoint extends IPoint { // если уберем extends, то as не сможем использовать
  z:string
}

const fun = (point:IPoint) => {
    // допустим мы хотим преобразовать d к типу I3DPoint
  let d:I3DPoint = point; // в таком случае будет ошибка
    // для этого мы будем использовать as
  const c = point as I3DPoint; // Теперь тип c I3DPoint
  // point как I3DPoint
}

Классический пример с html.

const myCanvas = document.getElementById('canvas'); 

Если мы наведем на элемент, то увидим, что ожидается

ts

С помощью as мы указываем конкретнее.

const myCanvas = document.getElementById('canvas') as HTMLCanvasElement; 

Теперь будет только HTMLCanvasElement

ts