如何基于第二个参数使用类型谓词收窄TypeScript联合类型?
实现带类型收窄的验证函数
要实现根据config.type收窄value类型的效果,你需要结合泛型和类型谓词(Type Predicate),让TypeScript能根据配置的类型和函数返回值,自动推导出value的具体子类型。
具体实现方案
建立类型映射关系
先定义一个映射类型,把config.type的取值和对应的Value子类型绑定,让TypeScript能通过type值定位到目标类型:type ConfigTypeToValue = { foo: Foo; bar: Bar; };定义泛型Config类型
让Config的type属性和上述映射关联,确保配置的类型合法且能关联到对应的Value子类型:type Config<T extends keyof ConfigTypeToValue> = { type: T };实现带类型谓词的验证函数
通过泛型约束和类型谓词,让函数返回true时,TypeScript自动将value收窄为对应子类型:function isValid<T extends keyof ConfigTypeToValue>( value: Value, config: Config<T> ): value is ConfigTypeToValue[T] { // 这里编写实际的校验逻辑 if (config.type === 'foo') { // 校验是否符合Foo类型的规则,比如检查专属属性是否存在 return 'something' in value; } else { // 校验是否符合Bar类型的规则 return 'somethingElse' in value; } }
完整示例代码
type Foo = { name: string; age: number; something?: string }; type Bar = { name: string; age: number; somethingElse?: string }; type Value = Foo | Bar; // 绑定config.type与Value子类型的映射 type ConfigTypeToValue = { foo: Foo; bar: Bar; }; // 泛型配置类型 type Config<T extends keyof ConfigTypeToValue> = { type: T }; const value: Value = { name: 'John', age: 22 }; // 带类型收窄的验证函数 function isValid<T extends keyof ConfigTypeToValue>( value: Value, config: Config<T> ): value is ConfigTypeToValue[T] { if (config.type === 'foo') { return 'something' in value; } else { return 'somethingElse' in value; } } // 测试类型收窄效果 const config: Config<'foo'> = { type: 'foo' }; if (isValid(value, config)) { // value自动收窄为Foo类型,可安全访问something属性 console.log(value.something); } const config2: Config<'bar'> = { type: 'bar' }; if (isValid(value, config2)) { // value自动收窄为Bar类型,可安全访问somethingElse属性 console.log(value.somethingElse); }
核心逻辑说明
- 类型映射:
ConfigTypeToValue明确了type取值和对应子类型的关联,是TypeScript实现类型推导的基础。 - 泛型约束:
T extends keyof ConfigTypeToValue确保传入的config.type只能是合法的取值,避免无效类型。 - 类型谓词:
value is ConfigTypeToValue[T]告诉TypeScript,当函数返回true时,value的类型就是映射中对应的子类型,从而自动完成类型收窄。
内容的提问来源于stack exchange,提问作者Martin Kadlec
相关产品推荐
相关产品推荐

