#5 TypeScript функції та їх параметри

Працючи з TS вам буде потрібно також вказувати типи для того, що приймають функції, та що віддають. Наприклад:

function greet(name: string): string {
    return `Привіт, ${name}!`;
}

console.log(greet("Олексій")); // Привіт, Олексій!

В середені дужок ви зазначаєте тип змінної, яку передаєте, а за дужками (: string {) те що вона будет повертати. Ви можете не вказати тип данних, який буде повертати функція, але в такому випадку TS задать його автоматично, і тоді в випадку повернення не того типа данних, ви отримаєте помилку.

function add(a: number, b: number) {
    return a + b; // TypeScript автоматично визначає тип як number
}

Необовʼязкові властивості

Також треба звернути увагу, що якщо ви вказали змінні, та їх типи в параметрах функції, ви їх не зможете не передати, тобто якщо ви не вкажете в прикладі вгорі поле b, то отримаєте помилку, томущо зазначене поле автоматично рахується як обовʼязкове. Якщо ж вам потрібно вказати поле, яке буде не обовʼязковим, то ви можете використати оператор ?:

function introduce(name: string, age?: number): string {
    return age ? `Мене звати ${name}, мені ${age} років.` : `Мене звати ${name}.`;
}

console.log(introduce("Анна")); // Мене звати Анна.
console.log(introduce("Анна", 25)); // Мене звати Анна, мені 25 років.

Значення за замовчуванням

В стандартному JS, значення за замовчуванням ви просто вказуэте через =, тут так само, але = стоїть після типу:

function power(base: number, exponent: number = 2): number {
    return base ** exponent;
}

console.log(power(3)); // 9 (3²)
console.log(power(3, 3)); // 27 (3³)

Скорочені функції

const myFunc = (a: number, b: number): number => a + b

Callback всередені функції

Тут все трохи складніше, але все одно зрозуміло, якщо придивитися:

function processUserInput(name: string, callback: (msg: string) => void): void {
    const message = `Користувач: ${name}`;
    callback(message);
}

processUserInput("Іван", console.log); // Користувач: Іван

Тобто, коли ви передаєте в функцію callback, там також треба вказати її тип. void - це тип данних який означає, що функція нічого не повертає. Як би виглядав void, в іншій функції, яка нічого не поветрає:

function gas(message: string): void {
    console.log(message);
}

gas("Іван"); // Іван

Перевантаження функцій (Function Overloads)

Перевантаження, це коли ви зазначаєте відразу декілька типів і параметрів:

function getLength(value: string): number;
function getLength(value: any[]): number;
function getLength(value: any): number {
    return value.length;
}

console.log(getLength("Привіт")); // 6
console.log(getLength([1, 2, 3, 4])); // 4

Але таку ковбасу писати зовсім не обовʼязково, тому що можна це написати як:

function getLength(value: string | any[] | number): number {
  if (typeof value === "number") {
    return value.toString().length;
  }
  return value.length;
}

Хоча, як перший так і другий варіант вважається вірним, хочу щоб ви звернули увагу на if typeof number -> value.toString(). Це по факту костиль, тому що тип number не має length, і якщо ви передасте масив чисел, то отримаєте помилку:

function getLength(value: string | string[] | number  {
  return value.length; // помилка 25 це число і length у нього немає
}

getLength(25) // помилка 25 це число і length у нього немає

Тому який варіант ліпше обирати вам, але мені здається що перше зазначення виглядає чистіше.

І на підсумок ось ще декілька параметрів:

never — функція ніколи не повертається

function throwError(msg: string): never {
    throw new Error(msg);
}

unknown — коли ми не знаємо точний тип

function processValue(value: unknown) {
    if (typeof value === "string") {
        console.log("Рядок:", value.toUpperCase());
    } else if (typeof value === "number") {
        console.log("Число:", value.toFixed(2));
    } else {
        console.log("Невідомий тип");
    }
}

processValue("hello"); // Рядок: HELLO
processValue(10.456); // Число: 10.46
processValue(true); // Невідомий тип

На цьому все, до наступного уроку.