Skip to main content

TypeScript

Источник  👀

Использование

Установка

npm i -g typescript
# or
yarn add global typescript

Запуск

tsc

Запуск с определенными настройками

tsc --project configs/my_tsconfig.json

Директивы ///

Ссылка на встроенные типы

/// <reference types="react-scripts" />

Ссылка на другие типы

/// <reference path="../my-types" />
/// <reference types="node" />

Комментарии для компилятора

Отключение проверки файла

// @ts-nocheck

Включение проверки файла

// @ts-check

Игнорирование следующей строки

// @ts-ignore

Ожидание ошибки на следующей строке

// @ts-expect-error

Операторы

  • ?? - оператор проверки на null или undefined
function getValue(n: number): number | 'nill' {
// 'nill' возвращается, если `n` - это любое ложное значение (включая `0` и пустую строку)
// return n || 'nill'

// 'nill' возвращается, только если `n` имеет значение `null` или `undefined`
return n ?? 'nill'
}
  • ?. - оператор опциональной последовательности
function countCaps(value?: string) {
// приведенное ниже выражение будет иметь значение `undefined`,
// если `value` имеет значение `null` или `undefined`
// или `match` не нашел совпадений
return value?.match(/[A-Z]/g)?.length ?? 0
}
  • ! - оператора утверждения ненулевого значения
let value: string | undefined

// код, инициализирующий переменную `value` (присваивающий ей какое-либо значение)

// утверждаем, что `value` имеет значение (определена)
console.log(`Значение переменной 'value' состоит из ${value!.length} символов`)
  • &&=
let x
let y = 1

// присваиваем значение, только если текущее значение является истинным
x &&= 'default' // `x` по-прежнему имеет значение `undefined`
y &&= 3 // `y` теперь имеет значение `3`
  • ||=
let x
let y = 1

// присваиваем значение, только если текущее значение является ложным
x ||= 'default' // `x` теперь имеет значение `default`
y ||= 3 // `y` по-прежнему имеет значение `1`
  • ??=
let x
let y = 0

// присваиваем значение, только если текущим значением является `null` или `undefined`
x ??= 'default' // `x` теперь имеет значение `default`
y ??= 2 // `y` по-прежнему имеет значение `0`

Основные типы

  • any - отсутствие типа
  • string - строка
  • number - число
  • boolean - логическое значение (true или false)
  • object - объект (не примитивное значение)
  • undefined - неинициализированное значение (например, переменная без значения или несуществующее свойство объекта)
  • null - явно установленное пустое значение
  • void - null или undefined (обычно, используется для типизации значения, возвращаемого функцией)
  • never - значение, которое не может возникнуть (например, когда выбрасывается исключение)
  • unknown - значение неизвестного на момент определения типа

Объектные типы

Объект

{
requiredString: string
optionalNumber?: number
readonly readOnlyBoolean: boolean
}

Объект с произвольным количеством свойств (например, хештаблица или словарь)

{ [key: string]: Type }
{ [key: number]: Type }
{ [key: symbol]: Type }
{ [key: `data-${string}`]: Type }

Литеральные типы

  • строковый - let direction: 'left' | 'right'
  • числовой - let roll: 1 | 2 | 3 | 4 | 5 | 6

Массивы и кортежи

Массив строк

string[]
// or
Array<string>

Массив функций, возвращающих строки

(() => string)[]
// or
{ (): string }[]
// or
Array<() => string>

Кортеж

let myTuple: [string, number, boolean?]

myTuple = ['test', 42]

Произвольный кортеж

type Numbers = [number, number]
type Strings = [string, string]

type NumAndStr = [...Numbers, ...Strings]
// [number, number, string, string]

type NumberAndRest = [number, ...string[]]
// [number, любое количество строк]

type RestAndBool = [...any[], boolean]
// [любое количество любых типов, boolean]

Именованный кортеж

type Vector2D = [x: number, y: number]

function createVector(...args: Vector2D) {}
// const createVector = (x: number, y: number) => {}

Функции

Функциональный тип

(arg1: Type, argsN: Type) => Type
// or
{ (arg1: Type, argN: Type): Type }

Конструктор

new () => ConstructedType
// or
{ new (): ConstructedType }

Функциональный тип с опциональным параметром

(arg1: Type, optional?: Type) => ReturnType

Функциональный тип с оставшимися параметрами

(arg1: Type, ...args: Type[]) => ReturnType

Функциональный тип со статическим свойством

{ (): Type; staticProp: Type }

Дефолтное значение параметра

function fn(arg = 'default'): ReturnType {}

Стрелочная функция

(arg: Type): ReturnType => {}
// or
(arg: Type): ReturnType => someValue

Типизация this

function fn(this: Type, arg: string) {}

Перегрузка

function fn(x: string): number
function fn(x: number): string
function fn(x: string | number): string | number {}

Объединение и пересечения

Объединение

let myUnion: number | string

Пересечение

let myIntersection: Foo & Bar

Именованные типы

Интерфейс

interface Child extends Parent, SomeClass {
requiredProp: Type
optionalProp: Type
optionalMethod?(arg: Type): ReturnType
}

// example
interface TodoItem {
id: string
text: string
done: boolean
}
interface TodoList {
todos: TodoItem[]
}
interface TodoActions {
addTodo: (todo: TodoItem) => void
updateTodo: (id: string) => void
removeTodo: (id: string) => void
}

Класс

class Child
extends Parent
implements Child, OtherChild {
prop: Type
defaultProp = 'default value'
private _privateProp: Type
private readonly _privateReadonlyProp: Type
static staticProp: Type

static {
try {
Child.staticProp = computeStaticProp()
} catch {
Child.staticProp = defaultValue
}
}

constructor(arg: Type) {
super(arg)
}

private _privateMethod(): Type {}

methodProp: (arg: Type) => ReturnType
overloadedMethod(arg: Type): ReturnType
overloadedMethod(arg: OtherType): ReturnType
overloadedMethod(arg: CommonType): CommonReturnType {}
static staticMethod(): ReturnType {}
subMethod(arg: Type): ReturnType {
super.subMethod(arg)
}
}

Перечисление (использовать не рекомендуется)

enum Options {
FIRST,
EXPLICIT = 1,
BOOLEAN = Options.FIRST | Options.EXPLICIT,
COMPUTED = getValue()
}

enum Colors {
Red = "#FF0000",
Green = "#00FF00",
Blue = "#0000FF"
}

Синонимы типов

type FullName = {
firstName: string
lastName: string
middleName?: string
}

type Direction = 'left' | 'right'

type ElementCreator = (type: string) => Element

type Point = { x: number, y: number }

type Point3D = Point & { z: number }

type PointProp = keyof Point // 'x' | 'y'

const point: Point = { x: 1, y: 2 }

type PtValProp = keyof typeof prop // 'x' | 'y'

type TodoItem = {
id: string
text: string
done: string
}
type TodoItemComponentProps = {
todo: TodoItem
updateTodo: (id: string) => void
removeTodo: (id: string) => void
}

Дженерики (общие типы)

Функция с типом параметров

<T>(items: T[], callback: (item: T) => T): T[]

Интерфейс с несколькими типами

interface Pair<T1, T2> {
first: T1
second: T2
}

Ограниченный тип параметра

<T extends ConstrainedType>(): T

Дефолтный тип параметра

<T = DefaultType>(): T

Ограниченный и дефолтный тип параметра

<T extends ConstrainedType = DefaultType>(): T

Общий кортеж

type Arr = readonly any[]

function concat(<U extends Arr, V extends Arr>(x: U, y: V): [...U, ...V] {
return [...x, ...y]
})

const strictResult = concat([1, 2] as const, ['3', '4'] as const)
// type -> [1, 2, '3', '4']

const relaxedResult = concat([1, 2], ['3', '4'])
// type -> Array<string | number>

Индексные, связанные (mapped) и условные типы

Типы индексов (keyof)

type Point = { x: number, y: number }
let pointProps: keyof Point = 'x'

function getProp<T, K extends keyof T>(
val: T,
propKey: K
): T[K] {}

Связанные типы

type Stringify<T> = { [P in keyof T]: string }

type Partial<T> = { [P in keyof T]?: T[P] }

Условные типы

type Swapper = <T extends number | string>
(val: T) => T extends number ? string : number

// ===
(val: number) => string // if T is number
(val: string) => number // if T is string

Условные связанные типы

interface User {
handle: string
email: string
age: number
}

type StringProps<T> = {
[K in keyof T]: T[K] extends string ? K : never
}

type UserStrings = StringProps<User>
// 'handle' | 'email'

Вспомогательные типы

Partial

Partial<{ x: number; y: number; z: number }>
// ===
{ x?: number; y?: number; z?: number }

Readonly

Readonly<{ x: number; y: number; z: number }>
// ===
{
readonly x: number
readonly y: number
readonly z: number
}

Pick

Pick<{ x: number; y: number; z: number }, 'x' | 'y'>
// ===
{ x: number; y: number }

Record

Record<'x' | 'y' | 'z', number>
// ===
{ x: number; y: number; z: number }

Exclude

type Excluded = Exclude<string | number, string>
// ===
number

Extract

type Extracted = Extract<string | number, string>
// ===
string

NonNullable

type NotNull = NonNullable<string | number | void>
// ===
string | number

ReturnType

type ReturnType = ReturnType<() => string>
// ===
string

InstanceType

class Renderer {}
type Instance = InstanceType<typeof Renderer>
// ===
Renderer

Предохранители

Предикаты типа

function isType(val: unknown): val is T {
// возвращает `true`, если `val` имеет тип `T`
}

if (isType(val)) {
// `val` имеет тип `T`
}

typeof

declare value: string | number | boolean
const isBoolean = typeof value === 'boolean'

if (typeof value === 'number') {
// значением `value` является число
} else if (isBoolean) {
// `value` имеет логическое значение
} else {
// значением `value` является строка
}

instanceof

declare value: Date | Error | MyClass
const isMyClass = value instanceof MyClass

if (value instanceof Date) {
// значением `value` является экземпляр `Date`
} else if (isMyClass) {
// значением `value` является экземпляр `MyClass`
} else {
// значением `value` является экземпляр `Error`
}

in

interface Dog { woof(): void }
interface Cat { meow(): void }

function speak(pet: Dog | Cat) {
if ('woof' in pet) {
pet.woof()
} else {
pet.meow()
}
}

Утверждения (присвоения)

Утверждение типа

let myVar = someVal as string
// or
let myVar = <string>someVal

Константа (иммутабельное значение)

let point = { x: 24, y: 42 } as const
// or
let point = <const>{ x: 24, y: 42 }

Декларации

Глобальные

declare const foo: number

declare function greet(greeting: string): void

Пространства имен

declare namespace myLib {
function createGreeting(s: string): string
let numberOfGreetings: number
}

declare namespace GreetingLib {
interface LogOptions {
verbose?: boolean;
}
interface AlertOptions {
modal: boolean;
title?: string;
color?: string;
}
}