一种类型定义,无需联合即可涵盖原始类型和泛型类型的属性

Posted

技术标签:

【中文标题】一种类型定义,无需联合即可涵盖原始类型和泛型类型的属性【英文标题】:One type definition to cover properties of primitive and generic types without unioning 【发布时间】:2017-01-12 13:02:41 【问题描述】:

这是需要我定义两种我想重构/整合的类型的模式:

...
.then((result1: any) => 
    let promises = 
       one: $q.when(val1),
       two: $q.when(val2)
    ;
    return $q.all(promises);
)
.then((resolvedPromises: any) => 
    // use
    resolvedPromises.one...
    resolvedPromises.two
);

我想定义 promisesresolvedPromises 的类型,但由于它们是类型相关的,我想定义一个类型(可能是泛型)而不是定义具有相似定义的两个类型。

所以而不是:

public interface ResultingType 
    [id: string]: any,
    one: Something1,
    two: Something1


public interface PromisingType 
    [id: string]: ng.IPromise<any>,
    one: ng.IPromise<Something1>,
    two: ng.IPromise<Something2>

问题在于,从通常的泛型类型的角度来看,我们提供了要注入的最内层类型,但在我的情况下,我需要以某种方式定义 outer输入 ng.IPromise&lt;&gt; 或实际上什么都没有。

我也不希望最终得到一个允许两种类型的单一类型:

public interface ConsolidatedType 
    [id: string]: any | ng.IPromise<any>,
    one: Something1 | ng.IPromise<Something1>,
    two: Something2 | ng.IPromise<Something2>

这将允许在无效的地方进行混合和匹配。所以这是不行的。有没有其他方法可以真正拥有一个没有代码重复的单一类型,只将类型包装到 Promise 中?

【问题讨论】:

我不确定我是否收到您的代码。如果promisesResultingType 类型,那么onetwo 不应该是承诺吗?当你给他们分配$q.when(...)?另外,为什么你将这些接口定义为可索引的(也就是说,为什么你有[id: string]: any?) 1. 为什么要建立索引? 为了满足$q.all 调用,因为它被定义为all(promises: [id: string]: IPromise&lt;any&gt;; ): IPromise&lt; [id: string]: any; &gt;,所以基本上我只定义了两个属于同一类型定义的附加预定义属性。 2. onetwo 是否应该作为结果的 promise? 不。因为我们应该在创建 deferred 时提供 promise,但是当它们被解决时,我们会得到它们的已解决值而不是已解决的承诺。请参阅我之前评论中的$q.all 定义。 【参考方案1】:

怎么样:

interface BaseType<T, S> 
    [id: string]: T;
    one: S;
    two: S;

然后:

...
.then((result1: any) => 
    let promises = 
       one: $q.when(val1),
       two: $q.when(val2)
     as BaseType<ng.IPromise<any>, ng.IPromise<Something1>>;
    return $q.all(promises);
)
.then((resolvedPromises: BaseType<any, Something1>) => 
    // use
    resolvedPromises.one...
    resolvedPromises.two
);

您还可以创建“快捷方式”:

interface PromiseType extends BaseType<ng.IPromise<any>, ng.IPromise<Something1>> 

interface ValueType extends BaseType<any, Something1> 

然后:

...
.then((result1: any) => 
    let promises = 
       one: $q.when(val1),
       two: $q.when(val2)
     as PromiseType;
    return $q.all(promises);
)
.then((resolvedPromises: ValueType) => 
    // use
    resolvedPromises.one...
    resolvedPromises.two
);

【讨论】:

这是一个可行的解决方案,虽然不是很好,因为我的预定义属性不是同一类型。如果我们有其中两个,我们最终会得到一个具有三个泛型子类型的泛型类型,如果更多它总是 N = exrea 属性的数量,那么我们就有一个具有 N+1 个子类型的泛型类型。

以上是关于一种类型定义,无需联合即可涵盖原始类型和泛型类型的属性的主要内容,如果未能解决你的问题,请参考以下文章

C#泛型

枚举和泛型

Java中数组和泛型的类型规则

普通集合和泛型集合的区别,哈希表和字典表的区别,队列和堆栈的区别以及堆和栈的区别。

枚举和泛型

swift中泛型和 Any 类型