如何将数组校验逻辑封装为函数且避免TypeScript类型错误?
问题
我想把start函数中的内联数组校验逻辑封装成validateParams函数,改成start1的形式,但调用后const assetConfig = params[0];出现两个TypeScript错误:
'params' is possibly 'undefined'.ts(18048)Element implicitly has an 'any' type because expression of type '0' can't be used to index type 'JSONRPCParams'. Property '0' does not exist on type 'JSONRPCParams'.ts(7053)
其中JSONRPCParams类型定义为type JSONRPCParams = object | any[];,且该类型来自外部模块无法修改。我尝试调整validateParams的逻辑,但错误依旧。
原代码如下:
type JSONRPCParams = object | any[]; // 来自外部模块,无法修改 async function start(params: JSONRPCParams | undefined) { // 希望把这段校验逻辑抽成函数 if (!params || !Array.isArray(params) || params.length === 0) { throw new Error('invalid parameter(s) provided'); } const assetConfig = params[0]; // 内联校验时无错误 } function validateParams(params: JSONRPCParams | undefined) { if (!params || !Array.isArray(params) || params.length === 0) { throw new Error('invalid parameter(s) provided'); } } async function start1(params: JSONRPCParams | undefined) { validateParams(params); const assetConfig = params[0]; // 抽成函数后出现错误 }
我也曾尝试如下写法,但问题未解决:
if (params && Array.isArray(params) && params.length >= 0) { return; } throw new Error('Invalid parameter(s) provided');
解决方案
问题核心是TypeScript无法通过普通函数调用自动缩小参数类型,需要把validateParams改成类型守卫函数,让TypeScript明确校验通过后params的具体类型。
写法1:返回类型谓词
修改validateParams,通过返回类型谓词告知TypeScript校验通过后params的类型:
function validateParams(params: JSONRPCParams | undefined): params is any[] { if (!params || !Array.isArray(params) || params.length === 0) { throw new Error('invalid parameter(s) provided'); } return true; } async function start1(params: JSONRPCParams | undefined) { validateParams(params); const assetConfig = params[0]; // 此时TypeScript确认params是any[],无错误 }
写法2:断言式类型守卫
使用asserts语法更直观表达校验逻辑,无需返回值:
function validateParams(params: JSONRPCParams | undefined): asserts params is any[] { if (!params || !Array.isArray(params) || params.length === 0) { throw new Error('invalid parameter(s) provided'); } } async function start1(params: JSONRPCParams | undefined) { validateParams(params); const assetConfig = params[0]; // 同样无错误 }
说明
- 两种写法都通过类型守卫机制,让TypeScript理解:只要
validateParams不抛出错误,params就一定是非空的any[]类型,既排除了undefined可能性,也明确了参数是数组而非普通对象,解决了索引访问的类型错误。
内容的提问来源于stack exchange,提问作者chuacw
相关产品推荐
相关产品推荐

