如何在TypeScript中限制函数返回数组长度为入参长度+1
在TypeScript中实现带长度约束的useLoading函数
要让TypeScript严格校验useLoading返回数组的解构长度,核心是利用可变参数元组和映射类型绑定输入参数与返回值的长度关系,具体实现如下:
类型定义与函数实现
import { useState } from 'react'; // 泛型函数约束:输入为任意数量返回Promise的函数组成的元组 function useLoading<T extends readonly (() => Promise<any>)[]>( ...fns: T ): [boolean, ...{ [K in keyof T]: () => Promise<void> }] { const [loading, setLoading] = useState(false); // 包装入参函数,添加loading状态管理逻辑 const wrappedFns = fns.map(fn => async () => { setLoading(true); try { await fn(); } finally { setLoading(false); } }) as { [K in keyof T]: () => Promise<void> }; return [loading, ...wrappedFns]; }
效果验证
正确用法(无TypeScript错误)
const fn1 = () => Promise.resolve(); const fn2 = () => Promise.resolve(); const fn3 = () => Promise.resolve(); // 解构数量与返回数组长度完全匹配,TS无报错 const [loading, cb1, cb2, cb3] = useLoading(fn1, fn2, fn3);
错误用法(TypeScript即时报错)
const [loading, cb1, cb2, cb3] = useLoading(fn1, fn2); // TS提示:类型"[boolean, () => Promise<void>, () => Promise<void>]"的元组长度为3,但此处需要4个元素。
扩展支持带参数的入参函数
如果你的入参函数需要接收参数,可以调整泛型约束,让包装后的函数原样支持参数传递,同时保留类型校验:
function useLoading<T extends readonly ((...args: any[]) => Promise<any>)[]>( ...fns: T ): [boolean, ...{ [K in keyof T]: (...args: Parameters<T[K]>) => Promise<void> }] { const [loading, setLoading] = useState(false); const wrappedFns = fns.map(fn => async (...args: Parameters<typeof fn>) => { setLoading(true); try { await fn(...args); } finally { setLoading(false); } }) as { [K in keyof T]: (...args: Parameters<T[K]>) => Promise<void> }; return [loading, ...wrappedFns]; }
内容的提问来源于stack exchange,提问作者Real
相关产品推荐
相关产品推荐

