В TypeScript массивы имеют тип элементов. Два эквивалентных синтаксиса:
// Синтаксис 1: тип[]
const names: string[] = ['Алексей', 'Мария', 'Иван']
const scores: number[] = [95, 87, 100]
// Синтаксис 2: Array<тип> (дженерик)
const names: Array<string> = ['Алексей', 'Мария', 'Иван']
const scores: Array<number> = [95, 87, 100]TypeScript не позволит добавить элемент не того типа:
const nums: number[] = [1, 2, 3]
nums.push(4) // OK
nums.push('пять') // Ошибка: Argument of type 'string' is not assignable to parameter of type 'number'readonly string[] или ReadonlyArray<string> — массив, который нельзя изменить:
const COLORS: readonly string[] = ['red', 'green', 'blue']
COLORS.push('yellow') // Ошибка: Property 'push' does not exist on type 'readonly string[]'
COLORS[0] = 'black' // Ошибка: Index signature in type 'readonly string[]' only permits reading
// Но читать можно:
console.log(COLORS[0]) // 'red'
console.log(COLORS.length) // 3
console.log(COLORS.map(c => c.toUpperCase())) // ['RED', 'GREEN', 'BLUE'] — не мутируетКортеж — массив **фиксированной длины** с **определёнными типами** на каждой позиции:
// Обычный массив — все элементы одного типа
const arr: number[] = [1, 2, 3, 4, 5] // любая длина
// Кортеж — фиксированная структура
type Point = [number, number]
const p: Point = [10, 20]
type Entry = [string, number, boolean]
const user: Entry = ['Алексей', 30, true]
// Деструктуризация кортежа
const [name, age, isActive] = user
console.log(name) // 'Алексей'
console.log(age) // 30
console.log(isActive) // trueTypeScript 4.0+ поддерживает именованные элементы кортежа — улучшает читаемость:
type Point3D = [x: number, y: number, z: number]
type UserRecord = [name: string, age: number, email: string]
const point: Point3D = [1, 2, 3]
const record: UserRecord = ['Алексей', 30, 'alex@mail.ru']Кортежи могут содержать rest-элементы — полезно для описания функций с переменным числом аргументов:
type StringsAndNumber = [...string[], number]
const example: StringsAndNumber = ['a', 'b', 'c', 42] // последний всегда number
type AtLeastTwo = [string, string, ...string[]]
const tags: AtLeastTwo = ['js', 'ts', 'react', 'vue'] // минимум 2 строкиКортежи часто используются для возвращения нескольких значений из функции (как в React useState):
function useState<T>(initial: T): [T, (value: T) => void] {
let state = initial
const setState = (value: T) => { state = value }
return [state, setState]
}
const [count, setCount] = useState(0)
// count имеет тип number
// setCount имеет тип (value: number) => voidRuntime валидация кортежей — создание, проверка структуры и операции с типизированными парами координат
// TypeScript проверяет кортежи при компиляции.
// Реализуем runtime-валидацию для демонстрации концепции.
// Создаёт и валидирует кортеж [x, y] — оба должны быть числами
function createPoint(x, y) {
if (typeof x !== 'number' || typeof y !== 'number') {
throw new TypeError(`createPoint ожидает два числа, получено [${typeof x}, ${typeof y}]`)
}
return [x, y]
}
// Валидирует что значение является кортежем [number, number]
function isPoint(value) {
return (
Array.isArray(value) &&
value.length === 2 &&
typeof value[0] === 'number' &&
typeof value[1] === 'number'
)
}
// Складывает два кортежа-точки
function addPoints(p1, p2) {
if (!isPoint(p1) || !isPoint(p2)) {
throw new TypeError('Оба аргумента должны быть кортежами [number, number]')
}
const [x1, y1] = p1
const [x2, y2] = p2
return createPoint(x1 + x2, y1 + y2)
}
// Вычисляет расстояние между двумя точками
function distance(p1, p2) {
if (!isPoint(p1) || !isPoint(p2)) {
throw new TypeError('Оба аргумента должны быть кортежами [number, number]')
}
const [x1, y1] = p1
const [x2, y2] = p2
return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
}
// Масштабирует точку
function scalePoint(point, factor) {
if (!isPoint(point) || typeof factor !== 'number') {
throw new TypeError('scalePoint: нужна точка и числовой коэффициент')
}
const [x, y] = point
return createPoint(x * factor, y * factor)
}
// Симуляция readonly — возвращает замороженный кортеж
function createReadonlyPoint(x, y) {
return Object.freeze(createPoint(x, y))
}
// --- Демонстрация ---
console.log('=== Создание точек ===')
const p1 = createPoint(3, 4)
const p2 = createPoint(6, 8)
console.log('p1:', p1) // [3, 4]
console.log('p2:', p2) // [6, 8]
console.log('\n=== Операции с точками ===')
console.log('p1 + p2:', addPoints(p1, p2)) // [9, 12]
console.log('distance:', distance(p1, p2)) // 5
console.log('p1 * 2:', scalePoint(p1, 2)) // [6, 8]
console.log('\n=== Деструктуризация кортежей ===')
const [x, y] = p1
console.log(`x=${x}, y=${y}`) // x=3, y=4
console.log('\n=== Readonly кортеж ===')
const frozen = createReadonlyPoint(1, 2)
console.log('frozen:', frozen)
try {
frozen[0] = 99 // В strict mode: TypeError
console.log('frozen после изменения:', frozen) // [1, 2] — не изменился
} catch (e) {
console.log('Ошибка изменения readonly:', e.message)
}
console.log('\n=== Ошибки типов ===')
try {
createPoint('10', 20) // TypeError
} catch (e) {
console.log(e.message)
}
try {
addPoints([1, 2], [3, 4, 5]) // TypeError — не кортеж
} catch (e) {
console.log(e.message)
}В TypeScript массивы имеют тип элементов. Два эквивалентных синтаксиса:
// Синтаксис 1: тип[]
const names: string[] = ['Алексей', 'Мария', 'Иван']
const scores: number[] = [95, 87, 100]
// Синтаксис 2: Array<тип> (дженерик)
const names: Array<string> = ['Алексей', 'Мария', 'Иван']
const scores: Array<number> = [95, 87, 100]TypeScript не позволит добавить элемент не того типа:
const nums: number[] = [1, 2, 3]
nums.push(4) // OK
nums.push('пять') // Ошибка: Argument of type 'string' is not assignable to parameter of type 'number'readonly string[] или ReadonlyArray<string> — массив, который нельзя изменить:
const COLORS: readonly string[] = ['red', 'green', 'blue']
COLORS.push('yellow') // Ошибка: Property 'push' does not exist on type 'readonly string[]'
COLORS[0] = 'black' // Ошибка: Index signature in type 'readonly string[]' only permits reading
// Но читать можно:
console.log(COLORS[0]) // 'red'
console.log(COLORS.length) // 3
console.log(COLORS.map(c => c.toUpperCase())) // ['RED', 'GREEN', 'BLUE'] — не мутируетКортеж — массив **фиксированной длины** с **определёнными типами** на каждой позиции:
// Обычный массив — все элементы одного типа
const arr: number[] = [1, 2, 3, 4, 5] // любая длина
// Кортеж — фиксированная структура
type Point = [number, number]
const p: Point = [10, 20]
type Entry = [string, number, boolean]
const user: Entry = ['Алексей', 30, true]
// Деструктуризация кортежа
const [name, age, isActive] = user
console.log(name) // 'Алексей'
console.log(age) // 30
console.log(isActive) // trueTypeScript 4.0+ поддерживает именованные элементы кортежа — улучшает читаемость:
type Point3D = [x: number, y: number, z: number]
type UserRecord = [name: string, age: number, email: string]
const point: Point3D = [1, 2, 3]
const record: UserRecord = ['Алексей', 30, 'alex@mail.ru']Кортежи могут содержать rest-элементы — полезно для описания функций с переменным числом аргументов:
type StringsAndNumber = [...string[], number]
const example: StringsAndNumber = ['a', 'b', 'c', 42] // последний всегда number
type AtLeastTwo = [string, string, ...string[]]
const tags: AtLeastTwo = ['js', 'ts', 'react', 'vue'] // минимум 2 строкиКортежи часто используются для возвращения нескольких значений из функции (как в React useState):
function useState<T>(initial: T): [T, (value: T) => void] {
let state = initial
const setState = (value: T) => { state = value }
return [state, setState]
}
const [count, setCount] = useState(0)
// count имеет тип number
// setCount имеет тип (value: number) => voidRuntime валидация кортежей — создание, проверка структуры и операции с типизированными парами координат
// TypeScript проверяет кортежи при компиляции.
// Реализуем runtime-валидацию для демонстрации концепции.
// Создаёт и валидирует кортеж [x, y] — оба должны быть числами
function createPoint(x, y) {
if (typeof x !== 'number' || typeof y !== 'number') {
throw new TypeError(`createPoint ожидает два числа, получено [${typeof x}, ${typeof y}]`)
}
return [x, y]
}
// Валидирует что значение является кортежем [number, number]
function isPoint(value) {
return (
Array.isArray(value) &&
value.length === 2 &&
typeof value[0] === 'number' &&
typeof value[1] === 'number'
)
}
// Складывает два кортежа-точки
function addPoints(p1, p2) {
if (!isPoint(p1) || !isPoint(p2)) {
throw new TypeError('Оба аргумента должны быть кортежами [number, number]')
}
const [x1, y1] = p1
const [x2, y2] = p2
return createPoint(x1 + x2, y1 + y2)
}
// Вычисляет расстояние между двумя точками
function distance(p1, p2) {
if (!isPoint(p1) || !isPoint(p2)) {
throw new TypeError('Оба аргумента должны быть кортежами [number, number]')
}
const [x1, y1] = p1
const [x2, y2] = p2
return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
}
// Масштабирует точку
function scalePoint(point, factor) {
if (!isPoint(point) || typeof factor !== 'number') {
throw new TypeError('scalePoint: нужна точка и числовой коэффициент')
}
const [x, y] = point
return createPoint(x * factor, y * factor)
}
// Симуляция readonly — возвращает замороженный кортеж
function createReadonlyPoint(x, y) {
return Object.freeze(createPoint(x, y))
}
// --- Демонстрация ---
console.log('=== Создание точек ===')
const p1 = createPoint(3, 4)
const p2 = createPoint(6, 8)
console.log('p1:', p1) // [3, 4]
console.log('p2:', p2) // [6, 8]
console.log('\n=== Операции с точками ===')
console.log('p1 + p2:', addPoints(p1, p2)) // [9, 12]
console.log('distance:', distance(p1, p2)) // 5
console.log('p1 * 2:', scalePoint(p1, 2)) // [6, 8]
console.log('\n=== Деструктуризация кортежей ===')
const [x, y] = p1
console.log(`x=${x}, y=${y}`) // x=3, y=4
console.log('\n=== Readonly кортеж ===')
const frozen = createReadonlyPoint(1, 2)
console.log('frozen:', frozen)
try {
frozen[0] = 99 // В strict mode: TypeError
console.log('frozen после изменения:', frozen) // [1, 2] — не изменился
} catch (e) {
console.log('Ошибка изменения readonly:', e.message)
}
console.log('\n=== Ошибки типов ===')
try {
createPoint('10', 20) // TypeError
} catch (e) {
console.log(e.message)
}
try {
addPoints([1, 2], [3, 4, 5]) // TypeError — не кортеж
} catch (e) {
console.log(e.message)
}Реализуй функцию `createPoint(x, y)` которая возвращает кортеж [x, y] с проверкой что оба аргумента — числа. Затем реализуй `addPoints(p1, p2)` которая принимает два таких кортежа и возвращает новый кортеж с суммой координат.
В createPoint: typeof x !== "number" || typeof y !== "number" — бросай TypeError. Возвращай [x, y]. В addPoints: проверяй Array.isArray(p), p.length === 2, typeof p[0] === "number" && typeof p[1] === "number". Деструктурируй const [x1, y1] = p1 и верни createPoint(x1 + x2, y1 + y2).
Токены для AI-помощника закончились
Купи токены чтобы задавать вопросы AI прямо в уроке