我正在设计一个通用的Slice<E>
类,该类表示一组实例的一部分实例。例如,如果我们有Todo
个实例,则切片可以代表所有已完成的实例。
如果Todo
类具有id
属性,我们想在hasID
实例上将true
设置为Slice
,以便我们也可以建立索引Slice
的{{1}}实例。有没有一种方法可以在运行时检测泛型参数是否具有和id
属性?
答案 0 :(得分:1)
没有代码,这里没有太多可以继续的事情了。
从表面上看:不,您不能在运行时分析泛型类型参数,因为类型系统为erased。在运行时,您只能分析运行时值,例如传递给构造函数的实际对象。在编译时,您可能可以使编译器根据通用类型参数为true
提供特定的false
或hasID
布尔文字类型。您可以同时做这两种事情,并希望您有一个解决方案,其中运行时值实际上与编译时类型匹配。
让我们尝试一下。这是一个可能的解决方案的草图:
class Slice<E> {
instances: E[]
hasID: E extends {id: any} ? true : false;
constructor(firstInstance: E, ...restInstances: E[]) {
this.hasID = 'id' in firstInstance as Slice<E>['hasID'];
this.instances = [firstInstance, ...restInstances];
}
}
为hasID
属性提供了一个conditional type,该属性评估E
类型的参数,如果存在true
则返回E['id']
,否则返回false
。
构造函数接受至少一个类型为E
的参数,在运行时分析其中的第一个参数id
以设置hasID
的运行时间值。
让我们看看它是否有效:
const sliceOne = new Slice({a: 1}, {a: 2});
sliceOne.hasID // false at compile time and runtime
const sliceTwo = new Slice({id: 1}, {id: 2});
sliceTwo.hasID // true at compile time and runtime
看起来不错。仍然有些边缘情况您可能需要担心,例如:
declare const notSure: object;
const oopsie = new Slice(notSure);
oopsie.hasID; // false at compile time, maybe true at runtime!
编译器无法验证object
是否具有id
属性,因此它为hasID
提供类型false
。但是,当然object
可能具有id
属性,因此hasID
可能在运行时为true
。有办法解决吗?也许。但这并不简单。问题是您是否有可能遇到这些情况以及您是否关心它们。
无论如何,希望这有意义并给您一些指导。祝你好运!