“只读"的用法在打字稿中 [英] Usages of "readonly" in TypeScript
问题描述
这个用法很简单:作为一个契约,函数doSomething
声明它不会改变接收到的参数.
This usage is very simple: as a contract, the function doSomething
declares it doesn't mutate the received parameter.
interface Counter {
name: string
value: number
}
function doSomething(c: Readonly<Counter>) {
// ...
}
let c = {
name: "abc",
value: 123
}
doSomething(c)
// Here we are sure that 'c.name' is "abc" and 'c.value' is '123'
用法 2:工厂声明其输出不可修改
使用此代码:
interface Counter {
readonly name: string
readonly value: number
inc(): number
}
function counterFactory(name: string): Counter {
let value = 0
return {
get name() {
return name
},
get value() {
return value
},
inc() {
return ++value
}
}
}
我们这里有一个成员只读值
,不能直接从外部修改.但是成员 inc()
可以改变该值.此外,成员 value
被声明为 readonly
但它的值正在改变.
We have here a member readonly value
that cannot be modified directly from the outside. But a member inc()
can mutate the value. Also, the member value
is declared as readonly
but its value is changing.
我想知道在成员 value
上使用 readonly
是否是一个好的方法.语法没问题.但是这个例子在 TypeScript 中语义正确吗?这是修饰符 readonly
的用途吗?
I would like to know if this use of readonly
on the member value
is a good way to proceed. The syntax is OK. But is this example semantically correct in TypeScript? Is that what the modifier readonly
is for?
推荐答案
属性上的 readonly
关键字并不能确保属性值是恒定的.没有对应的 TypeScript.对于 readonly 属性,我们唯一可以确定的是:
The readonly
keyword on a property does not ensure that the property value is constant. There's no TypeScript equivalent for that. The only things we can be sure with a readonly property are:
- 它的值不能从消费者端改变→用法1.
- 它可以是仅获取属性的推断类型→ 用法 2.请注意,如果未定义
counterFactory
返回类型,则推断与完全一样Counter
接口,见下面代码中的(A). - 它的值只能设置一次,并且只能在对象构造期间设置→参见下面的 (B).
- Its value can't be changed from the consumer side → usage 1.
- It can be the inferred type of a get-only property → usage 2. Note that, if the
counterFactory
return type is not defined, it is inferred exactly like theCounter
interface, see (A) in the code below. - Its value can be set only once and only during the object construction → see (B) below.
代码示例:
// (A) Usage 2 using type inference
const counter = counterFactory('foo');
type Counter = typeof counter; // Produce the exact same type as the previous `Counter` interface
counter.value = 10; // [Ts Error] Can not assign to 'value' because it is a constant or read-only property
// (B) Readonly property initialization
// (B1) With an object literal + interface
const manualCounter: Counter = { name: 'bar', value: 2, inc: () => 0 };
manualCounter.value = 3; // [Ts Error] Can not assign...
// (B2) With a class
class Foo {
constructor(public name: string, public readonly value: number) { }
inc() {
return ++this.value; // [Ts Error] Can not assign...
}
}
const foo = new Foo('bar', 3);
foo.value = 4; // [Ts Error] Can not assign...
// (C) Circumvent TypeScript
Object.assign(foo, { value: 4 }); // → No error neither in Ts, nor at runtime
这真的很令人困惑,因为它几乎就像一个常量属性!用法 2 和案例 C 证明不是.
It's really confusing because it's almost like a constant property! The usage 2 and the case C prove it's not.
这篇关于“只读"的用法在打字稿中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!