如何在 TypeScript 中正确键入 mapOptional 函数?
How to correctly type a mapOptional function in TypeScript?
我有以下函数,它接受一个可选值并将其映射到另一个值,除非它是 null
或 undefined
。我目前对此的解决方案如下所示:
type Return<I, R> = I extends null ? null
: I extends undefined ? undefined
: R;
/**
* Maps an optional value to another optional by a callback.
*
* @param input - The input value to map.
* @param callback - The callback to map the value.
* @returns An optional mapped value.
*/
export function mapOptional<I, R>(input: I, callback: (value: NonNullable<I>) => R): Return<I, R> {
if (input === null) {
return null as Return<I, R>;
}
if (typeof input === 'undefined') {
return undefined as Return<I, R>;
}
return callback(input!) as Return<I, R>;
}
有两件事让我很烦恼:
- 为什么我必须将 return 值转换为
Return<I, R>
?
- 为什么我必须使用 bang 运算符
!
让输入变成 NonNullable
?
非常感谢对我的解决方案进行改进!
现在条件类型与函数的 return 类型有一种奇怪的关系,但在你的情况下,你可以做一些小技巧,让重载具有尽可能广泛的类型,并处理边缘情况围绕已知 null
和 undefined
传递给函数:
function mapOptional<I = any, R = unknown>(input: null, callback: (value: I) => R): null
function mapOptional<I = any, R = unknown>(input: undefined, callback: (value: I) => R): undefined
function mapOptional<I, R>(input: I, callback: (value: NonNullable<I>) => R)
: I extends (undefined | null) ? I : R
function mapOptional<I, R>(input: I, callback: (value: I) => R) {
if (input === null) {
return null;
}
if (input === undefined) {
return undefined;
}
return callback(input);
}
mapOptional(undefined, x => x.toFixed()) // type is undefined
mapOptional(null, x => x + 5) // type is null
mapOptional(56, x => x + 5).toFixed() // works
declare const optionalNumber: number | undefined
const r = mapOptional(optionalNumber, x => x + 5) // undefined | number
if (r) {
console.log(r.toFixed())
}
我有以下函数,它接受一个可选值并将其映射到另一个值,除非它是 null
或 undefined
。我目前对此的解决方案如下所示:
type Return<I, R> = I extends null ? null
: I extends undefined ? undefined
: R;
/**
* Maps an optional value to another optional by a callback.
*
* @param input - The input value to map.
* @param callback - The callback to map the value.
* @returns An optional mapped value.
*/
export function mapOptional<I, R>(input: I, callback: (value: NonNullable<I>) => R): Return<I, R> {
if (input === null) {
return null as Return<I, R>;
}
if (typeof input === 'undefined') {
return undefined as Return<I, R>;
}
return callback(input!) as Return<I, R>;
}
有两件事让我很烦恼:
- 为什么我必须将 return 值转换为
Return<I, R>
? - 为什么我必须使用 bang 运算符
!
让输入变成NonNullable
?
非常感谢对我的解决方案进行改进!
现在条件类型与函数的 return 类型有一种奇怪的关系,但在你的情况下,你可以做一些小技巧,让重载具有尽可能广泛的类型,并处理边缘情况围绕已知 null
和 undefined
传递给函数:
function mapOptional<I = any, R = unknown>(input: null, callback: (value: I) => R): null
function mapOptional<I = any, R = unknown>(input: undefined, callback: (value: I) => R): undefined
function mapOptional<I, R>(input: I, callback: (value: NonNullable<I>) => R)
: I extends (undefined | null) ? I : R
function mapOptional<I, R>(input: I, callback: (value: I) => R) {
if (input === null) {
return null;
}
if (input === undefined) {
return undefined;
}
return callback(input);
}
mapOptional(undefined, x => x.toFixed()) // type is undefined
mapOptional(null, x => x + 5) // type is null
mapOptional(56, x => x + 5).toFixed() // works
declare const optionalNumber: number | undefined
const r = mapOptional(optionalNumber, x => x + 5) // undefined | number
if (r) {
console.log(r.toFixed())
}