TypeScript,扩展全局Object <k,v =“”>接口

时间:2019-02-13 00:58:24

标签: typescript

可以扩展通用的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>

1 个答案:

答案 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