TypeScript依赖参数控制流分析未生效,类型未正确收窄问题
TypeScript联合元组剩余参数无法被控制流收窄的原因
你预期通过TypeScript的「依赖参数控制流分析(Control Flow Analysis for Dependent Parameters)」实现参数类型收窄,但在以下TS 4.9.4的代码中:
class Model { name: string age: number } function findUnique(id: string, parent?: boolean) { return {name: 'foo', age: 33} } function findMany(skip: number, take: number){ return [{name: 'foo', age: 33}, {name: 'bar', age: 66}] } class Foo { read(page: number, psize: number): Model[] | null read(id: string, include: {parent?: boolean} | undefined): Model | null read(...args: [number, number] | [string, {parent?: boolean} | undefined]): Model | Model[] | null { if(typeof args[0] === 'string') { const [id, include] = args // as [string, {parent?: boolean} | undefined] return findUnique(id, include?.parent) } const [page, psize] = args // as [number, number] return findMany(page * psize, psize) } }
在if(typeof args[0] === 'string')分支内,TypeScript仍将args识别为[number, number] | [string, {parent?: boolean} | undefined]联合类型,而非收窄后的目标类型,原因如下:
- 依赖参数控制流分析的适用范围有限:该特性主要针对具名重载参数,而非剩余参数的联合元组类型。它是为了关联函数显式重载中不同参数的类型依赖(比如当第一个参数是string时,第二个参数对应某类型),但不会把剩余参数数组当作有依赖关系的参数组处理。
- 联合元组的元素检查无法自动收窄整个数组类型:TypeScript目前不支持通过检查数组单个元素的类型,来推断整个数组的联合元组类型分支。即使你确定args[0]是string,TS也不会自动把整个args元组收窄到对应的分支类型。
临时解决办法
可以在分支内通过类型断言手动收窄:
if(typeof args[0] === 'string') { const [id, include] = args as [string, {parent?: boolean} | undefined] return findUnique(id, include?.parent) }
或者自定义类型守卫函数来完整收窄args的类型:
function isStringArgs(args: [number, number] | [string, {parent?: boolean} | undefined]): args is [string, {parent?: boolean} | undefined] { return typeof args[0] === 'string' } // 在read函数内使用 if(isStringArgs(args)) { const [id, include] = args return findUnique(id, include?.parent) }
内容的提问来源于stack exchange,提问作者alfred
相关产品推荐
相关产品推荐

