【问题标题】:Type wrongly interpreted when overloading in Typescript在 Typescript 中重载时类型被错误解释
【发布时间】:2018-03-25 10:30:51
【问题描述】:

考虑以下类和具有两个实现的factory 方法

class SomeClass {
  public someId: number;
  public someProp: string;
  constructor(input) {
    // do some internal stuff with input;
  }
}
function factory(singleInput: {}): SomeClass;
function factory(multipleInput: Array<{}>): Array<SomeClass>;
function factory(singleOrMultipleInput: {} | Array<{}>): SomeClass | Array<SomeClass> {
  if (singleOrMultipleInput instanceof Array) {
    // case multiple input: Array<{}>
    const arrayOfSomeClass = singleOrMultipleInput.map(ro => new SomeClass(singleOrMultipleInput)); // indeed is shown as SomeClass[]
    return arrayOfSomeClass;
  } else {
    // case single input: {}
    const singleSomeClass = new SomeClass(singleOrMultipleInput); // indeed is shown as SomeClass
    return singleSomeClass;
  }
}

换句话说:当使用{} 作为参数(普通对象)调用factory 时,我希望它返回SomeClass 的实例。当使用对象数组[{}, {}, {}] 调用factory 时,我希望它返回SomeClass 的实例数组,例如[SomeClass, SomeClass, SomeClass]

下面的 sn-p 表明 TypeScript 解释不识别它。

const singleInput: {} = {};
const multipleInput: Array<{}> = [{}, {}, {}];
let singleResult = factory({}); // is SomeClass, as expected
const multipleResult = factory([{}]); // no longer is SomeClass[] ?!
singleResult.someId = 123;
multipleResult.someId = 456; // the interpreter should flag this as wrong
singleResult = multipleResult; // also shouldn't be possible without an warning from the interpreter

但是,在工厂方法中,arrayOfSomeClasssingleSomeClass 输入正确。为什么multipleResult 不会被解释器显示为SomeClass[]

后续问题:如何实现以使解释器显示我所期望的类型? (最好将工厂方法作为SomeClassstatic(通用?)方法(我意识到这可能可以通过避免重载来实现,但这不是我想要的)

【问题讨论】:

    标签: typescript overloading


    【解决方案1】:

    我不是 100% 确定,但似乎 instanceof 检查必须按照与重载相同的顺序进行。

    function factory(multipleInput: Array<{}>): Array<SomeClass>;
    function factory(singleInput: {}): SomeClass;
    function factory(singleOrMultipleInput: {} | Array<{}>): SomeClass | Array<SomeClass> 
    

    它按预期工作。

    编辑:编译器正在第一次重载并试图验证它。

    所以它可以使用对象数组传递给 else { } 块,没有错误, 至于编译器Array是{}的情况。

    更多更新:

    从这个角度来看,这似乎是一个错误。

    function acceptsObjectType(obj:{}) {
      return obj;
    }
    
    let a = [];
    a = acceptsObjectType(a);
    

    但这没关系。

    function acceptsObjectType(obj:{}) {
      return obj;
    }
    
    let a:{} = [];
    a = acceptsObjectType(a);
    

    【讨论】:

    • 天啊...你是对的。这似乎是一个 TypeScript 错误。打算再等一会儿,看看是否有人能就为什么提出适当的解释,如果没有,我会将你的答案标记为正确。
    • 我在任何地方都没有看到 TypeScript 错误......有什么问题?
    • 在 typescript 2.9 中,我收到一个错误“Type {} 不可分配给 type any[]”,但 type any[] 可分配给 {}。所以这不是一个错误。
    • 我觉得声明重载的顺序无关紧要(您的解决方案与我最初的示例相比)。可能不是bug,但(至少对我而言)这绝对是出乎意料的行为; afaik它不会像这样在例如C#。谢谢大家的投入!
    • 来自TypeScript handbook:“[编译器] 查看重载列表,并继续第一个重载尝试使用提供的参数调用函数。如果找到匹配项,它会选择这个重载是正确的重载。因此,习惯上按照从最具体到最不具体的顺序对重载进行排序。"
    猜你喜欢
    • 2014-06-04
    • 1970-01-01
    • 1970-01-01
    • 2014-05-30
    • 2021-04-11
    • 2018-01-11
    • 2020-12-31
    • 2019-08-19
    • 1970-01-01
    相关资源
    最近更新 更多