symbol
670字约2分钟
TypeScript
2023-01-30
✨symbol 类型
Symbol
是 ES2015 新引入的一种原始类型的值。它类似于字符串,但是每一个 Symbol
值都是独一无二的,与其他任何值都不相等。
Symbol
值通过Symbol()
函数生成。在 TypeScript 里面,Symbol
的类型使用symbol
表示。
let x: symbol = Symbol();
let y: symbol = Symbol();
x === y; // false
✨unique symbol
symbol
类型包含所有的 Symbol
值,但是无法表示某一个具体的 Symbol
值。
为了解决这个问题,TypeScript 设计了symbol
的一个子类型unique symbol
,它表示单个的、某个具体的 Symbol
值。
因为unique symbol
表示单个值,所以这个类型的变量是不能修改值的,只能用const
命令声明,不能用let
声明。
由于unique symbol
声明的类型是唯一的,所以它不能赋给其他变量。
// 正确
const x: unique symbol = Symbol();
// 报错
let y: unique symbol = Symbol();
const z: unique symbol = x; // 报错:Type 'typeof x' is not assignable to type 'typeof z'.(2322)
如果要 x
赋值给 z
, 可以用 typeof
来获取 x
的类型。
const z: typeof x = x;
注意
相同参数的Symbol.for()方法会返回相同的 Symbol 值。TypeScript 目前无法识别这种情况,所以可能出现多个 unique symbol 类型的变量,等于同一个 Symbol 值的情况。
const a: unique symbol = Symbol.for("foo");
const b: unique symbol = Symbol.for("foo");
上面示例中,变量a
和b
是两个不同的值类型,但是它们的值其实是相等的。
unique symbol
类型是 symbol
类型的子类型,所以可以将前者赋值给后者,但是反过来就不行。
const a: unique symbol = Symbol();
const b: symbol = a; // 正确
const c: unique symbol = b; // 报错
unique symbol
的作用:
- 用作属性名,这可以保证不会跟其他属性名冲突。
const x: unique symbol = Symbol();
const y: symbol = Symbol();
interface Foo {
[x]: string; // 正确
[y]: string; // 报错
}
- 用作类
(class)
的属性值,但只能赋值给类的readonly static
属性。
class C {
static readonly foo: unique symbol = Symbol();
}
✨类型推断
如果变量声明时没有给出类型,TypeScript 会自动推断某个 Symbol 值变量的类型。
let
命令声明的变量,推断类型为symbol
, 且let
命令声明的变量,如果赋值为另一个unique symbol
类型的变量,则推断类型还是symbol
。
// 类型为 symbol
let x = Symbol();
// 类型为 symbol
const y = x;
const
命令声明的变量,推断类型为unique symbol
, 但是,const
命令声明的变量,如果赋值为另一个symbol
类型的变量,则推断类型为symbol
。
// 类型为 unique symbol
const x = Symbol();
// 类型为 symbol
let y = x;