Изменение типа, если не null
Описание
Очень часто случается, что нужно из переменной типа T
достать какое-то свойство типа U
.
Иногда случается такое с переменной типа T | null
. В таком случае, если значение null
мы возвращаем null
, в противном случае достаем переменную типа U
. То есть результат может быть U | null
.
Реализация
Теперь эту же логику пытаюсь реализовать как функцию. Примерно так правда?
function map<T, U>(value: T, callback: (object: NonNullable<T>) => NonNullable<U>): U
... ну как бы чтобы использовать вот так:
type Nullable<T> = T | null;
let text: Nullable<string> = `Hello world`;
const size: Nullable<number> = map<Nullable<string>, Nullable<number>>(text, nonNullableText => nonNullableText.length);
В таком случае делаю простейшую реализацию:
function map<T, U>(value: T, callback: (object: NonNullable<T>) => NonNullable<U>): U {
if (value === null || value === undefined) return value; // null | undefined
else return callback(value); // NonNullable<U>
} // NonNullable<U> | null | undefined тот же самый U
Получаю ошибку Type 'T' is not assignable to type 'U'.
в части return value
.
Вопрос
Нуу, по идеи ошибка логичная, но в какой части логики я ошибся?
Как...
function map<T, U>(value: T, callback: (object: NonNullable<T>) => NonNullable<U>): U
...правильно реализовать?
Дополнительно
Заголовок можете изменить. Не смог правильно описать ошибку.
Ответы (1 шт):
Функция с типами:
function example<
T,
CB extends (obj: NonNullable<T>) => unknown,
R = T extends NonNullable<T> ? ReturnType<CB> : null
>(input: T, cb: CB): R {
return (
input === null || input === undefined
? null
: cb(input)
) as R;
}
const q1 = example(null, () => {});
const q2 = example('hello world', (str) => str.replace(/\s/g, '').length);
const q3 = example({ a: null, b: null }, (obj) => Object.keys(obj).join('/'));
Типы переменных в которых хранится результат выполнения:
const q1: null
const q2: number
const q3: string
[LOG]: null
[LOG]: 10
[LOG]: "a/b"