Перегрузка функции TypeScript с передачей переменной - PullRequest
0 голосов
/ 29 мая 2020

Я пытаюсь использовать перегрузку функций TypeScript:

function useEntityTranslation<T extends Translation>(entity: EntityWithTranslations): T;
function useEntityTranslation<T extends Translation>(entity: null): {};

function useEntityTranslation<T extends Translation>(entity: EntityWithTranslations | null): T | {} {
  // do smth and return T or {}
}

Это работает, если я назову его так:

useEntityTranslation<ProductTranslation>(product); // EntityWithTranslations type
useEntityTranslation<ProductTranslation>(null);

Но если продукт имеет тип EntityWithTranslations | null ( он находится в компоненте React: null до тех пор, пока объект не будет получен из api)

useEntityTranslation<ProductTranslation>(product); // EntityWithTranslations | null

TypeScript выдает ошибку No overload matches this call.

Это потому, что тип EntityWithTranslations | null не может быть назначен ни одному из две перегрузки.

Но как я могу сделать его понятным для TypeScript?

UPDATE :

Проблема также в том, что я не могу использовать полученное значение как известный тип

const translation = useEntityTranslation<ProductTranslation>(product);
translation.name // name doesn't exist in {}

Мой обходной путь - добавить еще одну перегрузку:

function useEntityTranslation<T extends Translation>(entity: EntityWithTranslations | null): { [name: string]: any }

Я использую translation, если product не равно null, поэтому я Я уверен, что translation относится к типу ProductTranslation.

Не очень хорошо (translation.name -> any), но, по крайней мере, работает

Ответы [ 2 ]

0 голосов
/ 29 мая 2020

Как вы заметили, TypeScript не разрешает перегрузки, разрешая объединение аргументов из разных сигнатур вызовов. Существует давнее открытое предложение microsoft / TypeScript # 14107 с просьбой об этом, но пока это не является частью языка.

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

function useEntityTranslation<T extends Translation>(entity: EntityWithTranslations): T;
function useEntityTranslation<T extends Translation>(entity: null): {};
function useEntityTranslation<T extends Translation>(entity: EntityWithTranslations | null): T | {};

function useEntityTranslation<T extends Translation>(
  entity: EntityWithTranslations | null
): T | {} {
  // do smth and return T or {}
  return null!;
}

И тогда она будет работать так, как вы хотите:

useEntityTranslation<ProductTranslation>(Math.random() < 0.5 ? product : null); // okay

Хорошо, надеюсь, что это поможет; удачи!

Детская площадка ссылка на код

0 голосов
/ 29 мая 2020

может это то, что вы хотите

function useEntityTranslation<T extends Translation>(entity?:EntityWithTranslations): T | {}
...