Nano Hash - криптовалюты, майнинг, программирование

Условный тип в зависимости от значения аргументов функции

Я пытаюсь объединить 2 отдельных метода Typescript в один с тем же именем getDevice. Первая функция требует только числа, чтобы вернуть Device или null в случае отсутствия устройства:

protected getDevice(deviceId: number): Device | null {
  const device = this.devicesService.getDevice(deviceId);
  if (device == null)
    console.warn(`Failed to get the device #${deviceId}.`);
  return device;
}

Вторая функция принимает 2 аргумента. Первый - это либо число (как в предыдущей функции), либо Device (результат предыдущей функции):

protected getDeviceAs<T extends DeviceType>(
  deviceOrId: Device | number,
  deviceType: (new (device: Device) => T),
): T | null {
  const device = typeof deviceOrId === 'number'
    ? this.devicesService.getDevice(deviceOrId)
    : deviceOrId as Device;
  if (device == null) {
    console.warn(`Failed to get the device #${deviceOrId}.`);
    return null;
  }
  return new deviceType(device);
}

Результат объединения двух методов будет примерно таким:

protected getDevice<T extends DeviceType>(
  deviceOrId: Device | number,
  deviceType: (new (device: Device) => T) | null = null,
): Device | T | null {
  let device: Device | null = null;
  // In case deviceOrId is a number
  if (typeof deviceOrId === 'number') {
    device = this.devicesService.getDevice(deviceOrId);
    if (device == null) {
      console.warn(`Failed to get the device #${deviceOrId}.`);
      return null;
    }
    if (deviceType == null) return device;
  }

  // getDeviceAs functionality
  return new deviceType(device);
}

Проблема в том, что я не могу понять, как правильно набрать всю функцию:

  • return type depends on the deviceOrId argument type:
    • if deviceOrId is a Device, then for sure the result must be T | null
    • если deviceOrId - это number, то это может быть Device | T | null
  • return type and deviceOrId depend on the deviceType argument:
    • if deviceType is a null then the deviceOrId must be of type number and return type of Device | null
    • если deviceType - это (new (device: Device) => T), то тип возврата должен быть T | null

Возможно ли это вообще в Машинописи? Если да, то как? Может быть, с какими-то уловками с перегрузкой функций?

07.08.2020

  • На самом деле это действительно просто, но, возможно, синтаксически неочевидно. Вы можете перегрузить сигнатуру метода столько раз, сколько вам нужно, чтобы сопоставить любое количество списков параметров с типами результатов. Когда сигнатура функции перегружена, реализация не влияет на набор перегрузки и не повреждает поверхность API. 07.08.2020
  • Подробную информацию см. В руководстве по машинописному тексту. typescriptlang.org/docs/handbook/functions.html# перегрузки 07.08.2020
  • Спасибо @AluanHaddad! Я полностью упустил ту часть, что реализация не способствует набору перегрузки. Теперь это имеет смысл. 07.08.2020

Ответы:


1

Есть простое решение проблемы. Вы можете перегружать функции в машинописном тексте (документация). Сначала вы объявляете функциональные подписи. В случае этого вопроса это будет:

protected getDevice(deviceId: number): Device | null;
protected getDevice<T extends DeviceType>(
  deviceOrId: Device | number,
  deviceType: (new (device: Device) => T),
): T | null;

Затем вы пишете реализацию функции, которая будет обрабатывать логику. Эта сигнатура функции реализации не будет рассматриваться как еще одна перегрузка. Полный код:

// Overload 1:
protected getDevice(deviceId: number): Device | null;
// Overload 2:
protected getDevice<T extends DeviceType>(
  deviceOrId: Device | number,
  deviceType: (new (device: Device) => T),
): T | null;
// Implementation:
protected getDevice<T extends DeviceType>(
  deviceOrId: Device | number,
  deviceType: (new (device: Device) => T) | null = null,
): Device | T | null {
  let device: Device | null = null;
  if (typeof deviceOrId === 'number') {
    device = this.devicesService.getDevice(deviceOrId);
    if (device == null) {
      console.warn(`Failed to get the device #${deviceOrId}.`);
      return null;
    }
    if (deviceType == null) return device;
  }
  return new deviceType(device);
}
07.08.2020
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

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

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..