Alexandroppolus
@Alexandroppolus
кодир

Как правильно подсказать тайпскрипту про вывод типа в шаблонной функции?

Суть:
type Value<T> = (() => T) | T

function funcStr(value: Value<string>): string {
  return typeof value === 'function' ? value() : value
}

function funcTpl<T>(value: Value<T>): T {
  return typeof value === 'function' ? value() : value
}


Функция получает на вход некое значение, если оное оказалось функцией, возвращает результат вызова, иначе - само значение.
В funcStr всё без проблем, а в funcTpl засада: проверка typeof value === 'function' превращает тип value не в (() => T), как задумано, а в (() => T) | (T & Function)
Видимо, дело в том, что Т может быть функцией, и TS пытается это дело как-то расширить/использовать..

Как сделать правильно? Да, можно снасильничать (value as (() => T))(), но это не ts-way.

Update:
Т может быть функцией, т.е. возможно такое
funcTpl(() => ()=>{})
  • Вопрос задан
  • 88 просмотров
Решения вопроса 1
bingo347
@bingo347 Куратор тега TypeScript
Crazy on performance...
Вариант 1, использовать кастомный тайп гвард:
type Value<T> = (() => T) | T

function isFunctionValue<T>(value: Value<T>): value is () => T {
    return typeof value === 'function'
}

function funcStr(value: Value<string>): string {
  return isFunctionValue(value) ? value() : value
}

function funcTpl<T>(value: Value<T>): T {
  return isFunctionValue(value) ? value() : value
}


Вариант 2, исключить возможность функции из T:
type Value<T> = T extends (...args: never[]) => unknown ? never : (() => T) | T

function funcStr(value: Value<string>): string {
  return typeof value === 'function' ? value() : value
}

function funcTpl<T>(value: Value<T>): T {
  return typeof value === 'function' ? value() : value
}
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы