假设我有一个适用于ID为$ ./bin/month_roll
enter +/- to inc/decrement month ('q' to quit)
month : 6 : -
month : 5 : -
month : 4 : -
month : 3 : -
month : 2 : -
month : 1 : -
month : 12 : -
month : 11 : -
month : 10 : +
month : 11 : +
month : 12 : +
month : 1 : +
month : 2 : -
month : 1 : -
month : 12 : -
month : 11 : -
month : 10 : +
month : 11 : +
month : 12 : +
month : 1 : +
month : 2 : +
month : 3 : q
个对象的函数,以及一个用于相同item
items
我想实现一个函数签名,用于将项添加到项集合中。为此,我需要强制嵌套在Collectable接口中的Item类型和Item类型是相同的
interface Item {
id: string
}
interface Collectable<T extends Item> extends Object {
entities: { [key: string]: T },
ids: string[]
};
允许这样的事情
export function addToCollection<C extends Collectable<T>> (collection: C, item: T): C
问题是我找不到这样做的方法,也没有将嵌套类型T指定为类型参数
有什么建议吗?
答案 0 :(得分:1)
您需要将T
添加到函数类型参数列表中:
export function addToCollection<T extends Item, C extends Collectable<T>> (collection: C, item: T): C {
return null;
}
declare var c: Collectable<{ id: string, n: string }>;
declare var d: { id: string, n: string };
addToCollection(c, d); // works T and C are inferred correctly
这也适用于派生类型:
interface Apple extends Item {
name : string;
size: number;
}
interface AppleCollectable extends Collectable<Apple>{
bushelSize: number
}
declare var apples: AppleCollectable;
declare var a: Apple;
addToCollection(apples, a); // Works correctly, returns AppleCollectable
declare var applesBase: Collectable<Apple>;
addToCollection(applesBase, a); // returns Collectable<Apple>
修改强>
上面实现的一个问题是以下代码编译:
addToCollection(apples, { id: "" })
typescript推断泛型参数的方式存在问题,它无法根据它所依赖的另一个类型参数推断T
(在本例中为C extends Collectable<T>
)。它可以检查它,但它不能推断它。
一种选择是锁定T
是谁,并采取Collectable<T>
export function addToCollection<T extends Item>(collection: Collectable<T>) {
return function (item: T): Collectable<T> {
return null; // Actual code
};
}
addToCollection(apples)(a); // Works
addToCollection(apples)({ id: "" }) // Does not work
此方法的问题是返回类型为Collectable<T>
而不是AppleCollectable
。对此的丑陋工作是指定参数两次,一次为Collection<T>
,一次为C
,但这绝对不是一个理想的解决方案:
export function addToCollection<T extends Item, C extends Collectable<T>>(collection: Collectable<T>, dummy: C) {
return function (item: T): C {
return null;
};
}
addToCollection(apples, apples)({ id: "" }) // returns AppleCollectable
然而,最简单的解决方案是将add
函数添加到接口:
interface Collectable<T extends Item> extends Object {
entities: { [key: string]: T },
ids: string[]
addToCollection(item: T): this;
};
interface AppleCollectable extends Collectable<Apple> {
bushelSize: number
}
apples.addToCollection(a).bushelSize // addToCollection return AppleCollectable
apples.addToCollection({ id: "" }) // does not work