可以扩展泛型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>

最佳答案

不能更改接口所具有的类型参数的数量。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

关于typescript - TypeScript,扩展全局Object <K,V>接口(interface),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54660963/

10-11 07:32