объявление функций стрелок машинописного текста в классах с возвращаемым типом - PullRequest
1 голос
/ 30 июня 2019

Может кто-нибудь объяснить, что на самом деле делает этот синтаксис функции?

из https://material -ui.com / компоненты / ящики /

  const toggleDrawer = (side: DrawerSide, open: boolean) => (
    event: React.KeyboardEvent | React.MouseEvent,
  ) => {
    if (
      event.type === 'keydown' &&
      ((event as React.KeyboardEvent).key === 'Tab' ||
        (event as React.KeyboardEvent).key === 'Shift')
    ) {
      return;
    }

    setState({ ...state, [side]: open });
  };

https://www.typescriptlang.org/docs/handbook/functions.html

Я думал, что второй набор паренов определяет тип возвращаемого значения как тип объединения, но, похоже, это не так, поскольку event передается в функцию ниже.

Например, например:

public toggleDrawer (side: DrawerSide, open: boolean):any {

превращая это в публичный метод класса, я думаю следующее:


  public toggleDrawer = (side: DrawerSide, open: boolean) => (
    event: React.KeyboardEvent | React.MouseEvent,
  ) => {
   ...
  }

Так что непонятно, почему он не использует синтаксис :return из других сигнатур метода TS.

Это какой-то причудливый синтаксис в TS с функциями стрелок, чтобы убедиться, что this - это то, что мы хотим, чтобы он был экземпляром класса?

1 Ответ

0 голосов
/ 30 июня 2019

Код использует функции высшего порядка , как предлагается в комментарии. Синтаксис действительно немного причудливый, но концепция довольно проста. Это просто функции, которые «принимают одну или несколько функций в качестве аргументов» и / или «возвращают функцию в качестве результата». Вот несколько примеров:

// HO that returns a function
const first = (a: number, b: number) => {
    return () => a + b;
}
const firstHo = first(21, 21);
console.log(firstHo()); // 42

// HO that takes a function
const second = (a: number, func: (b: number, c: string) => string) => {
    console.log(func(a, "Hello World"));
}
const feed = (a: number, b: string) => `${b} : ${a}`;
second(42, feed); // Hello World : 42

//HO that takes AND returns a function
const third = (a: number, func: (b: number, c: string) => string) => {
    return (d: number) => func(a + d, "Hello World");
}
const thirdHo = third(21, feed);
console.log(thirdHo(21)); // Hello World : 42

Я явно возвращаю лямбды для ясности, но любую из этих функций можно упростить до чего-то более похожего на вашу, что может быть немного сложнее понять:

(a: number, b: number) => () => a + b;

Пример в вашей ссылке делает его использование довольно ясным. В разметке вы увидите это:

onClick={toggleDrawer(side, false)}

Очевидно, вы устанавливаете здесь обработчик событий, но toggleDrawer не является обработчиком; это функция, которая предоставляет обработчик, поэтому он разрешает:

onClick={(event) => {...}}

Что касается вашего вопроса об использовании синтаксиса :return, я не могу сказать, почему автор сделал это таким образом, но я предполагаю, что это для простоты и читабельности. Ваш пример, полностью напечатанный с определенным возвращением, будет выглядеть так:

toggleDrawer = (side: DrawerSide, open: boolean) : (event: React.KeyboardEvent | React.MouseEvent) => 
    (event: React.KeyboardEvent | React.MouseEvent) => {...}

Это просто делает его загадочным, не предоставляя никакой дополнительной информации; это просто дублирует следующий бит кода, который уже дает вам подпись возвращаемой функции.


Чтобы ответить на другой (теперь удаленный) ответ: я не верю, что он делает это каррирование функций, которое "представляет собой метод преобразования оценки функции, которая принимает несколько аргументов для оценки последовательности функции, каждая с одним аргументом. " Что может вас заинтересовать, так это функция, которая каррирует другую функцию, сама по себе является функцией высшего порядка! Вот слишком упрощенный пример:

// add just adds three numbers
const add = (a: number, b: number, c: number) : number => a + b + c;

// curry takes a function that takes three numbers and returns a number
// and returns a series of functions that each take a single number which
// eventually calls the given function passing the three numbers in
const curry = (f: (a: number, b: number, c: number) => number) => 
    (a: number) => (b: number) => (c: number) => f(a, b, c);

const curriedAdd = curry(add);
const addOneTo = curriedAdd(1);
const addThreeTo = addOneTo(2);
const seven = addThreeTo(4);
console.log(seven); // 7
// You could also call it like so, though it makes currying pointless
console.log(curriedAdd(1)(2)(4)); // 7

Обе эти техники на первый взгляд кажутся эзотерическими, но они обе очень мощные, и вы, вероятно, используете одну или обе в своей повседневной жизни. Например, filter, map и forEach являются функциями высшего порядка. Вы передаете свою predicate функцию в filter, и алгоритм успешно применяет ее к каждому элементу в вашем массиве. Все, что беспокоит filter, - это то, что ваш предикат принимает элемент и возвращает логическое значение. При желании ваш предикат может быть функцией карри.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...