使用类型谓词实现参数类型收窄的问题
如何通过类型谓词实现联合类型的完整字段收窄?
我希望基于单个字段的类型实现类型收窄,但TypeScript在使用类型谓词时,并未像在if语句中直接使用原始操作符那样,收窄类型中其他参数的类型。请问我该如何让类型收窄正常工作?
export function isTrue(input: boolean | undefined | null): input is true { return input === true; } type Refine = | { b: true; c: 'bIsTrue'; } | { b: undefined; c: 'bIsUndefined'; } | { b: false; c: 'bIsFalse'; }; export function example() { const example = (null as unknown) as Refine; if (example.b === true) { example.b; // Type is: true example.c; // Type is: 'bIsTrue' } if (isTrue(example.b)) { example.b; // Type is: true example.c; // Type is: 'bIsTrue' | 'bIsUndefined' | 'bIsFalse' } }
解决方案
问题根源在于当前的类型谓词仅针对example.b这个独立字段,TypeScript无法将单个字段的类型收窄关联到整个Refine联合类型的成员上。要实现完整的类型收窄,需要将类型谓词改为针对整个Refine对象的判断:
修改后的代码
export function isTrueRefine(input: Refine): input is Extract<Refine, { b: true }> { return input.b === true; } type Refine = | { b: true; c: 'bIsTrue'; } | { b: undefined; c: 'bIsUndefined'; } | { b: false; c: 'bIsFalse'; }; export function example() { const example = (null as unknown) as Refine; if (example.b === true) { example.b; // Type is: true example.c; // Type is: 'bIsTrue' } if (isTrueRefine(example)) { example.b; // Type is: true example.c; // Type is: 'bIsTrue' } }
原理说明
- 使用
Extract<Refine, { b: true }>从联合类型中精准提取出b字段为true的子类型 - 类型谓词直接断言输入的整个对象属于该子类型,让TypeScript能够正确关联
b和c的类型依赖关系,从而实现完整的类型收窄
内容的提问来源于stack exchange,提问作者Daniel Centore
相关产品推荐
相关产品推荐

