【问题标题】:Narrow type on parameter with type predicate具有类型谓词的参数上的窄类型
【发布时间】:2022-07-29 09:19:05
【问题描述】:

我对根据单个字段的类型缩小类型感兴趣。但是,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'
  }
}

【问题讨论】:

    标签: typescript


    【解决方案1】:

    一种可能性是对整个对象执行缩小,然后访问它的属性:

    function hasTrueBProperty<T extends { b: unknown }>(object: T): object is T & { b: true } {
      return object.b === true;
    }
    
    declare const refine: Refine;
    if (hasTrueBProperty(refine)) {
      refine.b;  // Type is: true
      refine.c;  // Type is: 'bIsTrue'
    }
    

    要将属性作为参数传递给测试,请使用另一个泛型:

    function hasTrueProperty<P extends PropertyKey, T extends Record<P, unknown>>(object: T, prop: P): object is T & Record<P, true> {
      return object[prop] === true;
    }
    
    declare const refine: Refine;
    if (hasTrueProperty(refine, 'b')) {
      refine.b;  // Type is: true
      refine.c;  // Type is: 'bIsTrue'
    }
    

    【讨论】:

    • 嗯,确实希望有一些可以工作的东西,不管该字段的名称如何,所以它可以更通用
    • 如果需要,您可以将要检查的属性作为另一个参数传递
    • 你有什么例子吗?
    • 查看编辑.. .. .
    猜你喜欢
    • 2023-03-08
    • 1970-01-01
    • 2022-12-17
    • 2020-01-05
    • 1970-01-01
    • 2020-01-27
    • 2018-10-29
    • 2017-04-11
    • 2020-09-17
    相关资源
    最近更新 更多