【问题标题】:Arguments and return type not inferred properly in function typed as union在类型为联合的函数中未正确推断参数和返回类型
【发布时间】:2020-02-26 19:18:37
【问题描述】:

在下面的代码中,我定义了一个函数联合类型 GetThing,然后我将其用于 getThing 函数。

但是,当我检查namething 的类型时,它们都是any。我希望namestringthingThing1 | Thing2

此外,我希望getThing 函数的返回类型取决于thing 参数的类型,这应该由switch 推断出来,但我们甚至还没有走那么远。

interface Thing1 {
    type: "thing1";
}

interface Thing2 {
    type: "thing2";
}


type GetThing1 = (name: string, thing: Thing1) => string;
type GetThing2 = (name: string, thing: Thing2) => boolean;
type GetThing = GetThing1 | GetThing2;

const getThing: GetThing = (name, thing) => {
   switch (thing.type) {
      case "thing1": {
          return "thingy";
      }
      case "thing2": {
          return true;
      }
   }
}

这是 Typescript 中的错误,是 Typescript 无法处理的推理层太深,还是我遗漏了什么?

【问题讨论】:

    标签: typescript


    【解决方案1】:

    这是目前 Typescript 的限制。

    (对于您最初的问题,它们都是 any,因为它无法将该函数识别为 GetThing1 或 GetThing2 类型。但是,即使您手动将它们定义为 @,您仍然会遇到问题987654324@).

    我稍微简化了你的代码,以:

    type Foo = (v: number) => string;
    type Bar = (v: string) => boolean;
    type FooBar = Foo | Bar;
    
    const fooBar: FooBar = (v: number | string) => {
    
       switch (typeof v) {
          case "number": {
              return "thingy";
          }
          case "string": {
              return true;
          }
       }
    }
    
    console.log(fooBar('Bob'));
    

    这可能更清楚一点。

    您的 sn-p 不会输入 getThing 的输入,但它们暗示为:

    (name: string, thing: Thing1|Thing2)

    因此(为简单起见,使用上面的示例),FooBar 被定义为FooBar。也就是说,(number)=>string(string)=>bool

    从 Typescript 迂腐的角度来看,(number|string) => string | bool 与其中任何一个都不一样 - 它并不关心您是否正确编写了它并且类型是否可行。

    我相信this feature-request 中的核心问题是相同的,在further down 中给出了一些解决方法。从概念上讲,Typescript 处理显然不是一件小事。

    我推荐以下之一:

    type Foo = (v: number) => string;
    type Bar = (v: string) => boolean;
    type FooBar = Foo | Bar;
    
    let foo: Foo = (v: number) => {
        return "heyo";
    }
    let bar: Bar = (v: string) => {
        return true;
    }
    
    type FooBarDiscriminator = (v: number | string) => string | boolean;
    const fooBar1: FooBarDiscriminator = (v: number | string) => {
        switch (typeof v) {
            case "number": {
                return foo(v);
            }
            case "string": {
                return bar(v);
            }
        }
    }
    
    function fooBar2(v: number | string) {
        switch (typeof v) {
            case "number": {
                return foo(v);
            }
            case "string": {
                return bar(v);
            }
        }
    }
    
    console.log(fooBar1(0));
    console.log(fooBar1('Bob'));
    console.log(fooBar2(0));
    console.log(fooBar2('Bob'));
    

    【讨论】:

      猜你喜欢
      • 2017-05-15
      • 2022-01-07
      • 2020-01-23
      • 2021-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-15
      • 1970-01-01
      相关资源
      最近更新 更多