减少Typescript

时间:2016-11-15 10:39:01

标签: generics typescript

我想定义一个抽象基类

interface IMap<TItem> {
    [name: string]: TItem;
}

type Func<TParam, TResult> = (parameter: TParam) => TResult;

abstract class ItemBase<TItem> {
    items: IMap<TItem[]>;
    getItemKey: IMap<Func<TItem, number>>;

    itemsOn: IMap<number[]>; // stores enabled item IDs
    getItemOn: IMap<Func<TItem, boolean>>;

    abstract populate(): void;
}

我想存储组,如果相似但不同的项目以及每个组的ID getter功能,那么我可以轻松枚举显示其ID的这些组。

现在在扩展这个基类的子类中,我想定义一个特定的对象映射类型,即

interface IFriendsMap<TItem> extends IMap<TItem> {
    male: TItem;
    female: TItem;
}

class Ancestors extends ItemBase<Person> {
    populate(): void {
        // populate data
    }
    ...
}

我现在想要使用属性访问器运算符访问我的类型属性,而不是使用数组表示法:

let a = new Ancestors();

// I want these
a.items.male[0..n]
a.getItemKey.male(...)
a.itemsOn.male[0..n]
a.getItemOn.male(...)
// not this
a.items['male'][0..n]
a.getItemKey['male'](...)
a.itemsOn['male'][0..n]
a.getItemOn['male'](...)

由于我的基类中有许多不同的IMap<>属性,因此提供一个开放泛型类型作为ItemBase类的泛型类型参数是理想的,例如

class ItemBase<TItem, TMap<> extends IMap<>> {
    items: TMap<TItem[]>;
    ...
}

所以这样我可以很容易地传入我的自定义对象映射类型和属性访问器(s | w)应该工作:

class Ancestors extends ItemBase<Person, IFriendsMap<>> {
    ...
}

另一种可能性是,如果我们可以有部分。这样子类就可以扩展原来的IMap<T>类。

问题

一个类可以有多个属性,这些属性将符合具有相同属性的同一对象映射(IFriendsMap<T>,其属性具有不同类型的T)。有办法解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

好像你想要:

abstract class ItemBase<TItem, TSpecific> {
    items: IMap<TItem[]> & TSpecific;
    getItemKey: IMap<Func<TItem, number>>;

    itemsOn: IMap<number[]>; // stores enabled item IDs
    getItemOn: IMap<Func<TItem, boolean>>;

    abstract populate(): void;
}

也就是说,items属性必须符合IMap<TItem[]>TSpecific,无论是什么。然后假设你说:

class Ancestors extends ItemBase<Person, IFriendsMap<Person>> {
    populate(): void {
        // populate data
    }
}

这样,您说items既是具有Person类型属性的对象又是IFriendsMap<Person>。因此:

let a = new Ancestors();

// This works
a.items.male
// This also works
a.items['male']