TS 抱怨没有提供类型 "never" 的参数



假设我想让一个函数更灵活,允许作为参数:

  • 一个类型为number的元素
  • 任何泛型元素+将其转换为数字的转换器函数
type ElementConvertor<T> = T extends number ? never : (element: T) => number
function isNumber(x: any): x is number {
return typeof x === "number"
}
function evaluate<T>(element: T, toNumber: ElementConvertor<T>) {
if (isNumber(element)) return element
else return toNumber(element)
}

const main = () => {
const array1 = [1, 2, 3];
const array1Value = array1.map(x => evaluate(x)); 
// -> TS compiler complains here 
//input.tsx(7, 34): An argument for 'toNumber' was not provided.

const array2 = [{ value: 1 }, { value: 2 }, { value: 3 }]
const array2Value = array2.map((x => evaluate(x, ({ value }) => value)))

console.log(array1Value, array2Value)
}

TS游乐场链接

我错过了什么?感谢

您可以使用typescript重载签名。关于函数重载的文档

过载签名和实现:

//delcare overload signatures
function evaluate(element: number): number;
function evaluate<T>(element: T, toNumber: ElementConvertor<T>): number;
// implementation has to be compatibel with all overload signatures
function evaluate<T>(element: T, toNumber?: ElementConvertor<T>) {
if (isNumber(element)) return element
else {
if (toNumber !== undefined) {
return toNumber(element)
} else {
//even though it is not easy possible we have to handle it
throw new Error(`Cannot evaluate, the toNumber is not defiend, input is not a number. Input value: ${element}`)
}
}
}

记住,类型是不保证的,所以无论采用何种方法,您都可以使用以下代码轻松失败:

evaluate({} as number);
evaluate(undefined as any as number);

打字游戏场在这里

您可以使用以下条件类型内联您想要的行为:

function evaluate<T>(element: T, ...[toNumber]: T extends number ? [] : [toNumber: (element: T) => number]) {
if (typeof toNumber !== "undefined") return toNumber(element);
return element;
}

然而,这不像使用重载那样可读,但它确实有效。

游乐场

相关内容

  • 没有找到相关文章

最新更新