Fork me on GitHub

TypeScript中readonly和const

本文首发于我的个人Blog阿西BUG,欢迎大家批评指正

readonly 属性修饰符

readonly 是一个属性(property) 修饰符,顾名思义,在 TypeScript 中它可以把一个属性变成只读的。我们可以在 class/interface/type 定义中使用它,也可以用来定义一个函数的参数。既然是只读的意味着一旦定义了就不能再修改,所以这些属性必须在声明的时候或者在类中对它进行初始化。

TypeScript 类型系统允许你在一个 function 里使用 readonly 来标记参数属性。它能让你以一种更安全的方式工作(不可预期的改变通常会带来很糟糕的后果)。

1
2
3
4
5
6
7
8
function foo(config: { readonly bar: number, readonly bas: number }) {
// ..
}

const config = { bar: 123, bas: 123 };
foo(config);

// 现在你能够确保 'config' 不能够被改变了

当然,你也可以在 interface 和 type 里使用 readonly:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// type
type Foo = {
readonly bar: number;
readonly bas: number;
};
// 初始化
const foo: Foo = { bar: 123, bas: 456 };
// 不能被改变
foo.bar = 456; // Error: foo.bar 为仅读属性

// interface
interface Foo {
readonly [x: number]: number;
}
// 使用
const foo: Foo = { 0: 123, 2: 345 };
console.log(foo[0]); // ok(读取)
foo[0] = 456; // Error: 属性只读

你也能指定一个类的属性为只读,然后在声明时或者构造函数中初始化它们,如下所示:

1
2
3
4
5
6
7
class Foo {
readonly bar = 1; // OK
readonly baz: string;
constructor() {
this.baz = 'hello'; // OK
}
}

Readonly 映射类型

对于每个属性都要写一个 readonly 的做法实在是不够优雅。作为一个推崇 Less is more (lan duo) 的人,能够少写一点就尽量少写。有没有一种方法可以一键给所有属性添加 readonly 定义呢?有的,官方标准库 lib.es5.d.ts 提供了一个方法 Readonly 把对象上所有属性变为只读。

1
2
3
4
5
6
7
8
9
10
11
12
type Foo = {
bar: number;
bas: number;
};

type FooReadonly = Readonly<Foo>;

const foo: Foo = { bar: 123, bas: 456 };
const fooReadonly: FooReadonly = { bar: 123, bas: 456 };

foo.bar = 456; // ok
fooReadonly.bar = 456; // Error: bar 属性只读

NOTE: 需要注意的是,Readonly 只对它当前修饰的属性有效,并不会对嵌套属性产生影响:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
interface foo {
readonly bar: string;
readonly baz: {
hoo: number;
}
}
const fuu: foo = {
bar: 'bar',
baz: {
hoo: 1
}
}
fuu.baz = { hoo: 2 } // ❌
fuu.baz.hoo = 3; // ✅
// 要在嵌套里面再使用 Readonly<T>
interface foo {
readonly bar: string;
readonly baz: Readonly<{
hoo: number;
}>
}

与 const 区别

const:

  1. 用于变量;
  2. 变量不能重新赋值给其他任何事物

readonly:

  1. 用于属性
  2. 用于别名,可以修改属性

eg:

1
2
3
4
const foo = 123; // 变量
let bar: {
readonly bar: number; // 属性
};


— end —

Enjoy it ? Donate for it ! 欣赏此文?求鼓励,求支持!
>