Функции изменения результата в TypeScript

#typescript

#typescript

Вопрос:

Когда дело доходит до функций изменения результата в TypeScript, какая из них лучше?

  • Через объединение функций?
 type SomeType = () => number | (() => string) | (() => Promise<string>)
  
  • Или через объединение возвращаемого типа?
 type SomeType = () => number | string | Promise<string>
  

Есть ли рекомендация для этого, или это не имеет абсолютно никакого значения?

Обновить

Из того, что я теперь понимаю, это синтетическое дифференцирование типов TypeScript, которое переводится в точно такой же JavaScript и требует точно такой же обработки. Таким образом, разница заключается исключительно в TypeScript, хотя он несет идентичную логику.

Это делает его странным, не так просто понять, почему тип не тот же.

Комментарии:

1. Что вы подразумеваете под «лучше»? Они означают разные вещи: ссылка на игровую площадку

2. Это сбивает с толку. Логика этого типа заключается в том, что он должен быть одинаковым, если вы думаете о том, как работает JavaScript. Из вашего примера похоже, что именно TypeScript применяет разницу, разделяя два идентичных объявления, которые в конечном итоге всегда будут приводить к одному и тому же выполнению JavaScript. В JavaScript нет разницы в вызове, ожидаете ли вы функцию, которая может возвращать несколько типов, или это переменная-функция, которая возвращает один из типов.

3. Но TypeScript здесь для обеспечения безопасности типов. Если вам нужна функция, которая выдает только числа, это одно, если вам нужна функция, которая выдает либо число, либо строку, это другое. Нет никакой логики для представления обоих как одного и того же, если вы не хотите обоих. Это зависит от того, как вы собираетесь их использовать.

4. @VLAZ Идея безопасности типов заключается в том, чтобы путем объявления различать вещи, которые могут потребовать различной обработки. В нашем примере они могут и не быть, поэтому в TypeScript нет значения, сообщающего нам здесь, что эти две вещи разные, потому что это не так.

5. Я не согласен. Если у меня есть f с первым объявлением типа, и я делаю if (typeof f() === "number") , я могу сделать вывод, что это внутри if тела, f есть () => number . Если бы f мы использовали второе объявление, у меня нет никаких гарантий этого. Это разные объявления функций.

Ответ №1:

Они разные.

  • При этом вы говорите, что SomeType — это либо функция, которая возвращает число, либо функция, которая возвращает строку, либо функция, которая возвращает обещание строки. (Несколько функций)
 type SomeType = () => number | (() => string) | (() => Promise<string>)
  
  • Этим вы говорите, что SomeType — это функция, которая возвращает либо число, либо строку, либо обещание строки. (Одна функция)
 type SomeType = () => number | string | Promise<string>
  

Так что это действительно зависит от того, что вам нужно.

Комментарии:

1. Сказать, что эти две вещи разные, значит иметь возможность привести пример в JavaScript, где два результата могут потребовать разной обработки. Я не могу придумать ни одного, потому что я считаю, что за этими двумя нет логической разницы, это просто синтетическое различие TypeScript, которое просто существует, и по неизвестной причине.

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

3. » Но, возможно, мы что-то упускаем из виду или есть более широкая картина, для которой это должно вести себя именно так». Единственный раз, когда они ведут себя одинаково, — это если вы вызываете f() , затем проверяете результат, а затем решаете, как с ним обращаться. Это один из способов использования функции. Вы также можете вызвать f() и на основе первого результата решить, как обрабатывать любой следующий. Первое объявление позволяет это, второе — нет. Вы также можете повторно вызывать f() и собирать результаты в массив, а затем обрабатывать его. В зависимости от подписи, она либо однородная, либо содержит смешанные элементы.

4. Кроме того, тип, который вы можете возвращать либо существующей SomeType функцией, либо новой, скажем () => boolean . В качестве простого примера с. (f: SomeType | null) => f ?? (() => false) В этом случае, если объявление было первым, вы просто получаете расширенное объединение типов. Если это было второе, то у вас потенциально создается функция другого типа.