【发布时间】:2020-02-24 18:03:58
【问题描述】:
我想要一个不带参数的方法,该方法通常返回一个数组,或者当我知道只有一个项目时,只返回该数组的第一个元素。
注意:我无法更改 Thing 的形状或值,它来自外部应用程序,我只是围绕 Thing 的属性创建一个包装器。
interface Thing {
[key: string]: any;
}
class Getter <T> {
asArray: boolean;
things: Thing[];
prop: string;
constructor(prop: string, things: Thing[], asArray: boolean) {
this.asArray = asArray;
this.things = things;
this.prop = prop;
}
// THIS IS THE METHOD IN QUESTION
getProp(): T | T[] {
if (this.asArray) return things.map(t => t[this.prop]);
else return things[0][this.prop];
}
// MORE METHODS ARE HERE FOR CHECKING DATA
}
class ThingModel {
things: Thing[];
asArray: boolean;
constructor(asArray: boolean, ...things: Thing[]) {
this.asArray = asArray;
this.things = things;
}
get foo() {
// We know the values of Thing.foo are numbers
return new Getter<number>('foo', this.things, this.asArray);
}
get bar() {
// We know the values of Thing.foo are strings
return new Getter<string>('bar', this.things, this.asArray);
}
}
const allThings = new ThingModel(true, ...getAllThings());
const oneThing = new ThingModel(false, getOneThing());
// TypeScript cannot infer these types, and both are the union of
// T | T[] even though we know which it will be, so the caller is
// forced to still make other assertions or type casts.
const allFooProps = allThings.foo.getProp(); // we know it's number[]
const oneBarProp = oneThing.bar.getProp(); // we know it's a string
如果我坚持总是返回一个数组,有些调用就不那么直观了。
// It's awkward that oneThing here would return an array of one property.
const [oneProp] = oneThing.foo.getProp();
我想我明白为什么这不能开箱即用 - TypeScript 可能无法保证 Getter.asArray 在构造函数之后不会被更改,但是,我尝试使用 asArray 的只读属性作为好吧,它没有帮助。
重写不起作用,因为我没有参数,并且我无法扩展类并重写方法,因为它抱怨返回类型不一样。我不能使用泛型,因为在没有首先检查 ThingModel.asArray 属性的情况下,我还不知道构造函数 new Getter(...) 的类型,并且 ThingModel 不能有泛型,因为各个属性的类型都是不同的。
我能想到的唯一方法是定义一个 SingleGetter 类并重新实现 Getter 的每个方法,然后在 ThingModel 中为每个属性执行 if/else 以构造适当的 Getter 或 SingleGetter。我想这可能是最“正确”的方法 - 但感觉就像很多多余的代码,Getter 已经有正确的逻辑,而不是返回 values 或 values[0] 的开关。
有没有更简单的方法来帮助编译器知道我什么时候会得到一个值和一个数组?
【问题讨论】:
标签: typescript class generics