【问题标题】:Call Readonly function in Typescript在 Typescript 中调用 Readonly 函数
【发布时间】:2020-05-06 16:31:24
【问题描述】:

我正在使用不可变数据模型构建应用程序,但我遇到了以下死胡同:

我有一个存储为不可变的函数,如下例所示:

const f: Readonly<() => void> = () => {};
f();

调用f 时出现以下错误:

This expression is not callable.
  Type 'Readonly<() => void>' has no call signatures. (2349)

我不明白 Readonly 转换了什么会产生这种效果。

转换回 mutable 似乎不是解决方案。这会产生同样的错误:

export type Mutable<T> = {
    -readonly [K in keyof T]: T[K];
};

(f as Mutable<typeof f>)();

我希望了解此问题的根本原因,不一定要寻找解决方法,例如强制转换为确切的函数类型,或者不对函数应用 Readonly。

Link to playground.

【问题讨论】:

  • 将函数设为只读的预期目的是什么?您是否试图阻止其属性(例如f.apply)被重新分配?

标签: typescript


【解决方案1】:

您可以使用Readonly&lt;Function&gt; 表示函数的属性(例如applybindcall...)是只读的,并使用交集类型来保留函数的调用签名。

type ReadonlyFunction<F extends Function> = Readonly<Function> & F;

const f: ReadonlyFunction<() => void> = () => {};

// OK
f();

// Error: Expected 0 arguments, but got 2.
f(1, 2);

// Error: Cannot assign to 'apply' as it is a readonly property.
f.apply = 'foo';

Playground Link


Readonly&lt;() =&gt; void&gt; 不起作用的原因似乎是Readonly 是一个mapped type,所以它映射了() =&gt; void 类型的属性,而不是调用签名。

原来() =&gt; void 类型没有属性,例如keyof (() =&gt; void)never{ [K in keyof (() =&gt; void)]: any }{}

【讨论】:

  • 是的。我错过了{} 可分配给Readonly&lt;() =&gt; void&gt; 的事实,这是不允许我调用它的一个很好的理由。我想对我来说似乎不直观的是Readonly&lt;number&gt;number,但Readonly&lt;() =&gt; void&gt;不是() =&gt; void,即使"number""function"都是typeof的可能返回值。虽然我猜function 不是原始类型。我不能说 Readonly
猜你喜欢
  • 1970-01-01
  • 2012-11-04
  • 2017-02-01
  • 2015-11-22
  • 2021-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多