代码之家  ›  专栏  ›  技术社区  ›  CMCDragonkai

重载的Typescript签名,后面的参数类型根据第一个参数类型更改

  •  0
  • CMCDragonkai  · 技术社区  · 5 年前

    type ActionAsync<S> = {
      (order: boolean, seek: S, limit: number): Promise<number>
      (order: null, seekAfter: S, seekBefore: S): Promise<number>
    };
    
    async function foo() {
        return 5
    }
    
    const x: ActionAsync<Date> = async (order: boolean|null, seekOrSeekAfter: Date, limitOrSeekBefore: number | Date) => {
        if (order === null) {
            return foo();
        }
        if (order === true) {
            return limitOrSeekBefore + 43;
        } else if (order === false) {
            return foo();
        }
    }
    

    limitOrSeekBefore 应该是 number order boolean ,但应该是 S Date 什么时候 null .

    limitOrSeekBefore: any .

    0 回复  |  直到 5 年前
        1
  •  1
  •   jcalz    5 年前

    如果说“它不进行类型检查”,你的意思是编译器不理解它 order === true 意味着 limitOrSeekBefore 是一个 number ,那么这只是TypeScript中的一个设计限制。如果将arrow函数分配给具有多个调用签名的变量,则编译器不会对实现中的每个调用签名执行控制流分析。它只是基于实现签名执行一次传递,而且 order 是不相关的联合类型,编译器无法为您验证任何内容。

    典型的问题是 microsoft/TypeScript#38622 ,这里的“技术领先”一词

    请注意,在您的情况下,“正常”过载也会出现相同的问题:

    async function y(order: boolean, seek: Date, limit: number): Promise<number>;
    async function y(order: null, seekAfter: Date, seekBefore: Date): Promise<number>;
    async function y(order: boolean | null, seekOrSeekAfter: Date, limitOrSeekBefore: number | Date) {
      if (order === null) {
        return foo();
      }
      if (order === true) {
        return limitOrSeekBefore + 43; // error
      } else {
        return foo();
      }
    }
    

    Promise<number>


    为了让它工作,我建议你使用 type assertion 告诉编译器 限制器检查前 是一个

    const x: ActionAsync<Date> = async (order: boolean | null, seekOrSeekAfter: Date, limitOrSeekBefore: number | Date) => {
      if (order === null) {
        return foo();
      }
      if (order === true) {
        return limitOrSeekBefore as number + 43;
      } else {
        return foo();
      }
    }
    

    Playground link to code

    推荐文章