【问题标题】:Typescript how to augment Object class?打字稿如何增加对象类?
【发布时间】:2020-04-16 17:00:35
【问题描述】:

我熟悉 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 可用于任何对象,在本例中为字符串)

【问题讨论】:

    标签: typescript module-augmentation


    【解决方案1】:

    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 和/或export 的文件),您可以在全局范围内进行声明:
      declare global {
        interface Object {
          ...
        }
      }
      
      Global augmentation
    3. 在方法声明中使用this 参数在方法签名中声明this 的类型。见Polymorphic thistypes
    4. TypeScript 需要一种隐式理解特定类型的方法,为此,我们将使用泛型。见Generics
    5. 将以上所有内容放在一起,通过声明method&lt;T&gt;(this: T),我们让TypeScript 知道this 参数应该采用执行方法的类型的形式。这样,如果该方法存在于某个类型上(确实存在,因为我们扩充了 Object 接口),在该类型上使用它会导致 this 参数属于该类型。

    【讨论】:

    • 非常感谢,特别是指出this 处理。但是,使用 '42'.let(it =&gt; alert(it)) 行测试您的代码在 typescriptlang.org/play 中有效,但不适用于我的 tsc` 编译器。两个版本都是 3.8.3 有什么想法吗?
    • 注意:我必须写(Object.prototype as any),否则我的打字稿编译器将不接受在Object.prototype上定义let
    • 错误信息是error TS2339: Property 'let' does not exist on type '"42"'.
    • @fjf2002 如果您将Object.prototype 转换为any 这将不起作用,并且会给您显示的错误。如果您无法在Object.prototype 上定义let,那是因为您没有合并Object 接口。此代码是否在模块中(文件是否有importexport)?如果是这样,您需要将接口与declare global 范围合并。见:typescriptlang.org/docs/handbook/declaration-files/templates/…
    • @fjf2002 您提供了上面的链接;)这只是了解如何正确使用它的问题。我会在答案中添加解释
    猜你喜欢
    • 2019-04-11
    • 2021-10-24
    • 2023-03-07
    • 2019-06-15
    • 1970-01-01
    • 1970-01-01
    • 2015-05-26
    • 2018-11-06
    • 2018-09-15
    相关资源
    最近更新 更多