typescript - TS - 如何在此代码中捕获错误而不使用类型断言
我有以下代码,它是正确的,但维护起来比较棘手...
interface FuncContainer<F extends (..._: Array<any>) => any> {
func: F
args: Parameters<F>
}
const func: FuncContainer<typeof Math.min> = {
func: Math.min,
args: [3, 4]
}
console.log(func.func(...func.args))
const funcs: Array<FuncContainer<(..._: Array<any>) => any>> = [
{
func: Math.min,
args: [1, 2]
} as FuncContainer<typeof Math.min>,
{
func: fetch,
args: ["https://google.com"]
} as FuncContainer<typeof fetch>
]
console.log(funcs)
这段代码可以编译而不会报错。然而,问题出现在我有 Array<FuncContainer> 的时候。我希望能够在一个数组中放入不同参数签名的不同函数,因此我让函数变成了泛型。我还希望 TS 能确保每个数组元素内部的类型是一致的。为此,我在每个单独的数组元素中都有类型断言,但这容易出错,因为如果有人忘记在新的元素添加到 Array<FuncContainer> 时添加类型断言,是不会有警告的。如果没有类型断言,参数类型的错误将不会被捕获。
const funcs2: Array<FuncContainer<(..._: Array<any>) => any>> = [
{
func: Math.min,
args: ["5", "6"] // should error, but doesn't
}
]
有没有一种方法可以对数组进行注解,使每个数组元素在每个数组位置上都进行具体类型的类型检查,但不需要像这个代码片段那样手动进行类型断言?可能可以通过映射类型的某种方法吗?
编辑:将 unknown 改为 any,以便在游乐场中使用
答案#1
从开发体验的角度来看,这种事情最容易通过函数助手来完成:
function funcContainer<F extends (...args: any[]) => any>(func: F, args: Parameters<F>) {
return {func, args};
}
const funcs = [
funcContainer(Math.min, [1, 2]),
funcContainer(fetch, ["https://google.com"]),
funcContainer(Math.min, ["x"]), // <== Error as desired
];
console.log(funcs);
游乐场链接
不仅在参数列表中获得类型安全,还可以在任何从 TypeScript 获取信息的 IDE(如 VS Code)中获得参数建议:
答案#2
在 @T.J. Crowder 的回答基础上:这里有一个只需要一个通用函数的解决方案。
function createFuncs<
F extends ((...args: any[]) => any)[]
>(funcs: [...{ [K in keyof F]: [F[K], Parameters<F[K]>] }]) {
return funcs;
}
const funcs = createFuncs([
[Math.min, [1, 2]],
[fetch, ["https://google.com"]],
[Math.min, ["x"]], // <== Error as desired
]);
操场
