2014-01-27 16 views
4

作为一个智力练习,我想我会看到我可以在TypeScript(0.9.5)中实现一些.Net泛型成员的密切程度,但我得到的结果高达List<T>,但不确定我可以进步。 (我知道有这种解决方法,但我特别试图使用与.Net库中存在的相同的实现,主要是尝试了解TypeScript中仍然存在的限制)。TypeScript中的界面逆转因子

无论如何,忽略这样一个事实,即我似乎无法以任何有意义的方式重载我的构造函数,在.Net源构造函数List(IEnumerable<T> collection)检查传递的Enumerable不为null,然后将其转换为ICollection使用ICollection<T> c = collection as ICollection<T>

在打字稿我这样做var c: ICollection<T> = collection(回收是一个IEnumerable<T>),但出现以下错误:

Cannot convert 'IEnumerable<T>' to 'ICollection<T>': Type 'IEnumerable<T>' is missing property 'Add' from type 'ICollection<T>'

我当前的代码如下:

export module System { 

    export module Collections { 

     export interface IEnumerator { 
      MoveNext(): boolean; 
      Reset(): void; 
      Current(): any; 
     } 
     export interface IEnumerable { 
      GetEnumerator(): IEnumerator; 
     } 
     export interface ICollection extends IEnumerable { 
      CopyTo(array: any[], index: number): void; 
      Count(): number; 
      SyncRoot(): any; 
      IsSynchronized(): boolean; 
     } 
     export interface IList extends ICollection { 
      [index: number]: any; 
      Add(value: any): number; 
      Contains(value: any): boolean; 
      Clear(): void; 
      IsReadOnly: boolean; 
      IsFixedSize: boolean; 
      IndexOf(value: any): number; 
      Insert(index: number, value: any): void; 
      Remove(value: any): void; 
      RemoveAt(index: number): void; 
     } 

     export module Generic { 

      export interface IEnumerator<T> extends System.Collections.IEnumerator { 
       Current(): T; 
      } 
      export interface IEnumerable<T> extends System.Collections.IEnumerable { 
       GetEnumerator(): IEnumerator<T>; 
      } 
      export interface ICollection<T> extends IEnumerable<T> { 
       Add(item: T): void; 
       Clear(): void; 
       Contains(item: T): boolean; 
       CopyTo(array: T[], arrayIndex: number): void; 
       Remove(item: T): boolean; 
       Count(): number; 
       IsReadOnly(); boolean; 
      } 
      export interface IList<T> extends ICollection<T> { 
       IndexOf(item: T): number; 
       Insert(index: number, item: T): void; 
       RemoveAt(index: number): void; 
       [index: number]: T; 
      } 
      export interface IReadOnlyCollection<T> extends IEnumerable<T> { 
       Count(): number; 
      } 
      export interface IReadOnlyList<T> extends IReadOnlyCollection<T> { 
       [index: number]: T; 
      } 

      export class List<T> implements IList<T>, System.Collections.IList, IReadOnlyList<T> { 
       private _defaultCapacity: number = 4; 

       private _items: T[]; 
       private _size: number; 
       private _version: number; 
       private _syncRoot: any; 

       constructor(collection?: IEnumerable<T>, capacity?: number) { 
        // NOTE: Capacity will be ignored is Collection is not null 
        //  This is because we don't appear to be able to overload ctors in TypeScript yet! 
        if (collection == null) { 
         if (capacity == null) { 
          this._items = new Array<T>(0); 
         } 
         else { 
          this._items = new Array<T>(capacity); 
         } 
        } else { 
         var c: ICollection<T> = collection; 

        } 
       } 
      } 
     } 
    } 
} 

有任何人试图CO /禁忌变化,其接口?如果是这样,你是怎么做的?

感谢,

+1

也许演员:'var c:ICollection = >集合;' – WiredPrairie

+0

感谢WiredPrairie,做直接演员似乎是有效的! –

+0

插件:@TomTregenna我在TypeScript中有一个用于常见数据结构的库:https://github.com/basarat/typescript-collections – basarat

回答

2

虽然打字稿不直接支持CO /禁忌变化,你可以只使用在这种情况下一个类型断言(这恰好看起来像C#等语言铸造):

var c: ICollection<T> = <ICollection<T>>collection; 

TypeScript没有确认类型断言操作是否正确的简单方法(例如collection对象实际上是ICollection<T>),因此您需要确定这对您是否重要。

而且,如果你想another想法简化代码一点,你可以使用默认值,为capacity参数:

constructor(collection?: IEnumerable<T>, capacity: Number = 0) { 
    if (!collection) { 
     this._items = new Array<T>(capacity); 
    } else { 
     var c: ICollection<T> = <ICollection<T>> collection; 
    } 
} 

打字稿编译器会生成看起来像这样的价值进行检查:

if (typeof capacity === "undefined") { capacity = 0; } 
5

您可以打字稿使用类型断言抑制警告:

var c: ICollection<T> = <ICollection<T>> collection; 

类型断言实际上不会转换值 - 在运行时,这些类型的注释或断言都不存在,因为它们全部被删除。运行时值完全不受类型断言的影响。

但是这并不能解决你不会有add方法的问题。

此外,null是这里测试一个不可能的值:

if (collection == null) { 

null通常只用于故意缺席值,你更有可能遇到undefined,例如。您可以测试这两种使用短手:

if (!collection) { 

我知道你执行的是智力活动,所以这下绝对注释不适用 - 但谁都值得注意的是重建的事情像列表和集合方法来复制.NET错过了TypeScript(和JavaScript)是一种不同的语言。您的TypeScript程序中的所有数组都是通用的,因此您可以通过所有这些不同的方式将它们包装起来,从而获得很少的好处 - 这些都只是开销。但正如我所提到的,作为一种智力活动,这是一件有趣的事情。

+1

参数*在编译时检查。如果你传递了'1',那绝对不会与参数的类型注释兼容,即'IEnumerable ':'构造函数(集合?:IEnumerable ,容量?:数字){' – Fenton

+0

我现在知道我测试了什么 - 我的界面是空的 - 所以没有什么可检查的。 :) – WiredPrairie

+0

哈!我也曾这样做过。结构类型确实有一些需要注意的地方:) – Fenton