在Typescript

时间:2018-03-25 10:30:52

标签: typescript overloading

考虑以下类和具有两个实现的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]

下面的代码段显示解释的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[]

跟进问题:如何实施,以便口译员按照我的预期显示类型? (最好将工厂方法作为static的{​​{1}}(通用?)方法(我意识到这可以通过避免重载来实现,但这不是我正在寻找的)

1 个答案:

答案 0 :(得分:1)

我不是100%肯定,但似乎必须以与重载相同的顺序进行实例检查。

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

它按预期工作。

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

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

的情况

更多更新:

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

function acceptsObjectType(obj:{}) {
  return obj;
}

let a = [];
a = acceptsObjectType(a);

但这没关系。

function acceptsObjectType(obj:{}) {
  return obj;
}

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