接口逆变在打字稿 [英] Interface Contravariance in TypeScript

查看:120
本文介绍了接口逆变在打字稿的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为一个智力练习,我以为我会看到我是如何紧密地可以实现一些打字稿的净泛型成员(0.9.5),我就得到了以列表< T> ; ,但不知道我能进步

As an intellectual exercise, I thought I'd see how closely I could implement some of the .Net generics members in TypeScript (0.9.5), I've gotten as far as List<T> but not sure I can progress.

(我知道有变通办法这一点,但我专门尝试使用相同的实现作为存在于净库,主要是为了尝试并获得限制仍然存在于打字稿)的想法。

(I realise there are workarounds for this, but I'm specifically trying to use the same implementation as exists in .Net libs, mostly to try and get an idea of the limitations still present in TypeScript).

无论如何,我似乎不是忽略了一个事实,以做能过载我的构造函数以任何有意义的方式,在净源构造列表(IEnumerable的< T>集合)检查,传递的可枚举不为空,然后contravariantly用它投射到一个ICollection的的ICollection< T> C =集合作为ICollection的< T>

Anyway, ignoring the fact that I don't seem to be able to overload my constructors in any meaningful way, in the .Net source the constructor List(IEnumerable<T> collection) checks that the passed Enumerable is not null, and then contravariantly casts it to an ICollection using ICollection<T> c = collection as ICollection<T>.

在打字稿我这样做 VAR C:ICollection的< T> =集合(集合是一个的IEnumerable< T> ),但出现以下错误:

In TypeScript I do this var c: ICollection<T> = collection (collection is an IEnumerable<T>), but get the following Error:

无法将'的IEnumerable< T>'到'的ICollection< T>'类型'的IEnumerable< T>'缺少财产类型'添加'的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 /禁忌方差与接口?如果是这样,你怎么了?

Has anyone else tried co/contra-variance with interfaces? If so, how did you get on?

谢谢,

推荐答案

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

While TypeScript does not directly support co/contra-variance, you can just use a type assertion in this instance (which happens to look like a cast in other languages like C#):

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



打字稿没有确认该类型断言操作是正确的(例如是一个简单的方法对象实际上是一个的ICollection< T> ),所以你需要决定是否这就是对你很重要

TypeScript doesn't have a simple way of confirming that the type assertion operation was correct (like is the collection object actually an ICollection<T>), so you'll need to decide whether that's important to you.

和,如果你想另一个想法简化代码位,你可以使用默认值的容量参数:

And, if you want another idea to simplify the code a bit, you could use a default value for the capacity parameter:

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



打字稿编译器将生成该值的检查看起来是这样的:

The TypeScript compiler will generate a check for the value that looks like this:

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

这篇关于接口逆变在打字稿的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆