打字稿如何扩充对象class?

Typescript how to augment Object class?

我熟悉 Kotlin 扩展函数 let(及相关)(参见 https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/let.html)。

我想在 TypeScript 中使用类似的东西,使用扩充(或者称为声明合并?)。所以我想我可以将 let 方法添加到 Object 超类。

我该怎么做?我想到了类似下面的东西,但这没有用。 Typescript好像没有扩充,只是单独使用下面的接口。

interface Object {
  let<T, R>(block: (t: T) => R): R
}

(Object.prototype as any).let = function<T, R>(block: (t: T) => R) {
  return block(this)
}

编辑:

测试用例为:

'42'.let(it => alert(it))
'foo'.let(it => it.toUpperCase())

(即 let 可用于任何对象,在本例中为字符串)

TL;DR

interface Object {
  let<T, R>(this: T, block: (t: T) => R): R;
}

Object.prototype.let = function <T, R>(this: T, block: (t: T) => R): R {
  return block(this);
};

'42'.let(it => alert(it)); // let -> Object.let<string, void>(this: string, block: (t: string) => void): void
(42).let(it => alert(it)); // let -> Object.let<number, void>(this: number, block: (t: number) => void): void
'foo'.let(it => it.toUpperCase()); // let -> Object.let<string, string>(this: string, block: (t: string) => string): string
['foo'].let(it => it[0].toUpperCase()); // let -> Object.let<string[], string>(this: string[], block: (t: string[]) => string): string

codepan

编辑 1

更新以上内容以反映 this 参数 + 示例的更好输入

编辑 2

说明

  1. Object 接口上声明 let 将该声明与 Object 接口的其余部分合并。参见 Declaration merging
  2. 如果这个声明在一个模块中(一个包含 import and/or export 的文件),你可以在全局范围内进行声明:
    declare global {
      interface Object {
        ...
      }
    }
    
    参见 Global augmentation
  3. 在方法声明中使用 this 参数在方法签名中声明 this 的类型。参见 Polymorphic thistypes
  4. TypeScript 需要一种隐式理解特定类型的方法,为此,我们将使用泛型。参见 Generics
  5. 将以上所有内容放在一起,通过声明 method<T>(this: T),我们让 TypeScript 知道 this 参数应该采用执行方法的类型的形式。这样,如果该方法存在于一个类型上(它确实存在,因为我们扩充了 Object 接口),在该类型上使用它会导致 this 参数属于该类型。