界面,typescript"/>

首页 > 解决方案 > TypeScript,扩展全局对象界面

问题描述

可以扩展通用Array接口

declare global {
  interface Array<T> {
    asClist(): Clist<T>
  }
}

并编写类似的代码const list = [1, 2].asClist(),它会list正确推断为Clist<number>

但它不适用于 Object,我尝试使用下面的代码但它不起作用,因为global Object似乎没有泛型类型<K, V>

declare global {
  interface Object<K, V> {
    asCmap(): Cmap<K, V>
  }
}

我尝试编写代码以正确const cmap = { a: 1, b: 2 }.asCmap()推断类型为.cmapCmap<string, number>

标签: typescript

解决方案


您无法更改接口具有的类型参数的数量。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

推荐阅读