Как определить тип для функции-коллбэка (как любой тип функции, а не универсальный any) в параметре метода
У меня есть определение типа, которое выглядит следующим образом:
interface Param {
title: string;
callback: any;
}
Мне нужно что-то подобное:
interface Param {
title: string;
callback: function;
}
Однако второй вариант не принимает компилятор. Как правильно описать тип для callback
, чтобы он был функцией?
5 ответ(ов)
Глобальный тип Function
выполняет эту задачу.
Кроме того, если вы планируете вызывать этот коллбэк без аргументов и игнорировать его возвращаемое значение, тип () => void
подходит для всех функций, которые не принимают аргументов.
В TypeScript, начиная с версии 1.4, появился ключевое слово type
, которое позволяет объявлять псевдонимы типов, аналогичные typedef
в C/C++. Вы можете объявить тип вашей функции обратного вызова следующим образом:
type CallbackFunction = () => void;
Это объявляет функцию, которая не принимает аргументов и ничего не возвращает. Если вам нужна функция, которая может принимать ноль или более аргументов любого типа и ничего не возвращает, то вы можете использовать следующий синтаксис:
type CallbackFunctionVariadic = (...args: any[]) => void;
После этого вы можете, например, сделать так:
let callback: CallbackFunctionVariadic = function(...args: any[]) {
// выполняем какие-то действия
};
Если вам нужна функция, которая принимает произвольное количество аргументов и может возвращать любой тип (включая void
), вы можете объявить так:
type CallbackFunctionVariadicAnyReturn = (...args: any[]) => any;
Также можно указать некоторые обязательные аргументы, а затем набор дополнительных аргументов (например, строку, число и далее произвольное количество дополнительных аргументов) следующим образом:
type CallbackFunctionSomeVariadic =
(arg1: string, arg2: number, ...args: any[]) => void;
Это может быть полезно, например, для обработчиков событий в EventEmitter.
Функции можно типизировать так строго, как вам нужно, хотя вы можете увлечься этим и столкнуться с комбинаторными проблемами, если попытаетесь все зафиксировать с помощью псевдонима типа.
Следуя ответу Райана, я думаю, что интерфейс, который вы ищете, можно определить следующим образом:
interface Param {
title: string;
callback: () => void;
}
Вы можете определить тип функции в интерфейсе различными способами:
- Общий способ:
export interface IParam {
title: string;
callback(arg1: number, arg2: number): number;
}
- Если вы хотите использовать синтаксис свойств, то:
export interface IParam {
title: string;
callback: (arg1: number, arg2: number) => number;
}
- Если сначала объявить тип функции, то:
type MyFnType = (arg1: number, arg2: number) => number;
export interface IParam {
title: string;
callback: MyFnType;
}
Использование очень просто:
function callingFn(paramInfo: IParam): number {
let needToCall = true;
let result = 0;
if (needToCall) {
result = paramInfo.callback(1, 2);
}
return result;
}
- Вы также можете объявить литерал типа функции, что означает, что функция может принимать другую функцию в качестве параметра. Параметрическая функция также может называться колбеком.
export interface IParam {
title: string;
callback(lateCallFn?: (arg1: number, arg2: number) => number): number;
}
Вот пример функции, которая принимает коллбэк:
const sqk = (x: number, callback: ((_: number) => number)): number => {
// коллбэк получает число и должен вернуть число
return callback(x * x);
}
// здесь наш коллбэк будет принимать число
sqk(5, function(x) {
console.log(x); // 25
return x; // здесь мы должны вернуть число
});
Если вас не волнуют возвращаемые значения коллбеков (большинство людей не знает, как эффективно их использовать), вы можете использовать void
:
const sqk = (x: number, callback: ((_: number) => void)): void => {
// коллбэк получает число, нам не важно, что он возвращает
callback(x * x);
}
// здесь наш коллбэк будет получать число
sqk(5, function(x) {
console.log(x); // 25
// void
});
Обратите внимание на сигнатуру, которую я использовал для параметра callback
:
const sqk = (x: number, callback: ((_: number) => number)): number
Я бы сказал, что это недостаток TypeScript, потому что мы должны предоставить имя для параметров коллбека. В этом случае, я использовал _
, потому что его нельзя использовать внутри функции sqk
.
Однако, если вы сделаете так:
// опасно!! не делайте этого
const sqk = (x: number, callback: ((number) => number)): number
Это валидный TypeScript, но его будет неправильно интерпретировать как:
// остерегайтесь! TypeScript будет думать, что это ...
const sqk = (x: number, callback: ((number: any) => number)): number
То есть, TypeScript подумает, что имя параметра число — это number
, а подразумеваемый тип — any
. Это явно не то, что мы имели в виду, но, увы, так работает TypeScript.
Так что не забудьте указать имена параметров при типизации ваших функций... как бы глупо это ни казалось.
Как преобразовать строку в число в TypeScript?
Как динамически назначить свойства объекту в TypeScript?
Как удалить элемент массива в TypeScript?
Что такое "*.d.ts" в TypeScript?
TypeScript ошибка TS2304: не удается найти имя 'require'