可以扩展通用的Array
接口
declare global {
interface Array<T> {
asClist(): Clist<T>
}
}
并编写类似const list = [1, 2].asClist()
的代码,它将正确地推断list
的类型为Clist<number>
但是它不适用于对象,我尝试在下面使用代码,但由于global Object
似乎没有通用类型<K, V>
declare global {
interface Object<K, V> {
asCmap(): Cmap<K, V>
}
}
我尝试制作代码const cmap = { a: 1, b: 2 }.asCmap()
来正确推断cmap
的类型为Cmap<string, number>
。
答案 0 :(得分:3)
您不能更改接口具有的类型参数的数量。 Array
已经是具有一个类型参数的泛型,Object
不是泛型的,这就是为什么一个有效而另一个无效的原因。
如果使用this
参数并将推断方法调用的实际对象推断为类型参数,则可以实现所需的效果。使用此类型参数,您可以根据需要提取键和值:
interface Object {
asCmap<TThis>(this: TThis): Cmap<keyof TThis, TThis[keyof TThis]>
}
const cmap = { a: 1, b: 2 }.asCmap() // CMap<"a" | "b", number>
我们可以使用条件类型来扩大键的类型:
type Widen<T extends PropertyKey> = PropertyKey extends infer P ? P extends any ? T extends P ? P : never : never : never;
interface Object {
asCmap<TThis>(this: TThis): Cmap<Widen<keyof TThis>, TThis[keyof TThis]>
}
const cmap = { a: 1, b: 2 }.asCmap(); // Cmap<string, string
const cmapNr = { 1: 1, b: 2 }.asCmap(); // Cmap<number|string, string>
enum E {
A, B
}
const cmapEnum = { [E.A]: 1, b: 2 }.asCmap(); // Cmap<string | number, string