如何让TypeScript在条件块中识别泛型推断的参数精确类型?
解决TypeScript泛型参数在分支中无法收窄类型的问题
原代码中泛型T仅作为宽泛约束(extends StatusCode),TypeScript无法通过switch分支的枚举值判断,反向关联params的具体类型。以下是几种可行的解决方式:
方案1:使用函数重载
通过重载定义明确不同枚举值对应的参数类型,实现部分TypeScript可自动识别分支内的参数类型:
enum StatusCode { ERROR = 411, GENERAL_ERROR = 400 } interface StatusCodeParams { [StatusCode.ERROR]: { name: string; age: number; }; [StatusCode.GENERAL_ERROR]: {}; } // 重载定义:明确每个状态对应的参数类型 function getMessage(statusCode: StatusCode.ERROR, params: StatusCodeParams[StatusCode.ERROR]): string; function getMessage(statusCode: StatusCode.GENERAL_ERROR, params: StatusCodeParams[StatusCode.GENERAL_ERROR]): string; // 函数实现 function getMessage(statusCode: StatusCode, params: StatusCodeParams[keyof StatusCodeParams]) { switch (statusCode) { case StatusCode.ERROR: return `Name '${params.name}' (age: ${params.age}) is invalid`; // 参数类型正确识别 default: return `Something went wrong`; } };
方案2:自定义类型守卫
通过类型守卫函数,显式关联枚举值与参数类型,让TypeScript在分支中正确收窄类型:
enum StatusCode { ERROR = 411, GENERAL_ERROR = 400 } interface StatusCodeParams { [StatusCode.ERROR]: { name: string; age: number; }; [StatusCode.GENERAL_ERROR]: {}; } // 自定义类型守卫:判断当前参数是否为ERROR对应的类型 function isErrorParams( statusCode: StatusCode, params: StatusCodeParams[keyof StatusCodeParams] ): params is StatusCodeParams[StatusCode.ERROR] { return statusCode === StatusCode.ERROR; } const getMessage = <T extends StatusCode>(statusCode: T, params: StatusCodeParams[T]) => { if (isErrorParams(statusCode, params)) { return `Name '${params.name}' (age: ${params.age}) is invalid`; // 参数类型正确识别 } else { return `Something went wrong`; } };
方案3:改用对象映射逻辑
将不同状态的处理逻辑映射为对象,TypeScript会自动根据枚举key推断对应的参数类型,写法更简洁:
enum StatusCode { ERROR = 411, GENERAL_ERROR = 400 } interface StatusCodeParams { [StatusCode.ERROR]: { name: string; age: number; }; [StatusCode.GENERAL_ERROR]: {}; } // 映射不同状态的消息生成逻辑 const messageHandlers = { [StatusCode.ERROR]: (params: StatusCodeParams[StatusCode.ERROR]) => `Name '${params.name}' (age: ${params.age}) is invalid`, [StatusCode.GENERAL_ERROR]: () => `Something went wrong` } const getMessage = <T extends StatusCode>(statusCode: T, params: StatusCodeParams[T]) => { return messageHandlers[statusCode](params); // 自动推断参数类型,无类型报错 };
内容的提问来源于stack exchange,提问作者Lemour
相关产品推荐
相关产品推荐

