Как интеллектуальное упражнение, я подумал, что посмотрю, как я мог бы реализовать некоторые из .Net-генераторов в TypeScript (0.9.5), я дошел до List<T>
, но не уверен, что я может прогрессировать.Контравариантность интерфейса в TypeScript
(Я понимаю, что для этого есть обходные пути, но я специально пытаюсь использовать ту же реализацию, что и в .Net-библиотеках, в основном, чтобы попытаться понять ограничения, все еще присутствующие в TypeScript).
В любом случае, игнорируя тот факт, что я не могу перегрузить конструкторы каким-либо значимым образом, в источнике .Net конструктор List(IEnumerable<T> collection)
проверяет, что переданный Enumerable не является нулевым, а затем контравариантно передает его в 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;
}
}
}
}
}
}
Кто-нибудь еще пытался со/противопоказаны дисперсия с интерфейсами? Если да, то как вы это сделали?
Спасибо,
Может быть, актерский состав: 'var c: ICollection = > коллекция;' –
WiredPrairie
Спасибо WiredPrairie, сделав прямое действие, действительно действует! –
Plug: @TomTregenna У меня есть библиотека для общих структур данных в TypeScript: https://github.com/basarat/typescript-collections – basarat