TypeScript中的Symbol,确实唯一。。。

Symbol

目录

  • Symbol
    • 目录
    • 自动推断
    • symbol
    • unique symbol
    • 区别

自动推断

  • let命令声明的变量,推断类型为 symbol。
    // let定义symbol推断为symbol
    let sym = Symbol(); //symbol
    
  • 但是,const命令声明的变量,如果赋值为另一个 symbol 类型的变量,则推断类型为 symbol。
    // let声明的symbol一定是symbol,然后复制给另一个const也是symbol
    let sym03 = Symbol(); //symbol
    // 类型为 symbol
    const sym04 = sym03; // const sym04=symbol()
    
  • let命令声明的变量,如果赋值为另一个 unique symbol 类型的变量,则推断类型还是 symbol。
    // 这里推断一定是US,赋值给let也是symbol
    const sym05 = Symbol();
    // 类型为 symbol
    let sym06 = sym05;
    

symbol

Symbol 是 ES2015 新引入的一种原始类型的值。它类似于字符串,但是每一个 Symbol 值都是独一无二的,与其他任何值都不相等。

Symbol 值通过Symbol()函数生成。在 TypeScript 里面,Symbol 的类型使用symbol表示。

let x:symbol = Symbol();
let y:symbol = Symbol();x === y // false

上面示例中,变量xy的类型都是symbol,且都用Symbol()生成,但是它们是不相等的。

unique symbol

symbol类型包含所有的 Symbol 值,但是无法表示某一个具体的 Symbol 值。

但是比如,6是一个具体的数值,就用6这个字面量来表示,这也是它的值类型。但是,Symbol 值不存在字面量,必须通过变量来引用,所以写不出只包含单个 Symbol 值的那种值类型。

为了解决这个问题,TypeScript 设计了symbol的一个子类型unique symbol,它表示单个的、某个具体的 Symbol 值。

因为**unique symbol表示单个值,所以这个类型的变量是不能修改值的,只能用const命令声明,不能用let**声明。

// 正确
const x:unique symbol = Symbol();// 报错
let y:unique symbol = Symbol();

上面示例中, **​let命令声明的变量,不能是unique symbol**类型,会报错。

因为unique symbol表示单个值,所以这个类型的变量是不能修改值的,只能用const命令声明,不能用let声明。

const x:unique symbol = Symbol();
// 等同于
const x = Symbol();

每个声明为unique symbol类型的变量,它们的值都是不一样的,其实属于两个值类型。

const sym07:unique symbol = Symbol();
const sym08:unique symbol = Symbol();sym07 === sym08 // 报错
sym08 === sym07 // 报错

上面示例中,变量a和变量b的类型虽然都是unique symbol,但其实是两个值类型。不同类型的值肯定是不相等的,所以最后一行就报错了。

const命令为变量赋值 Symbol 值时,变量类型默认就是unique symbol,所以类型可以省略不写。

const x:unique symbol = Symbol();
// 等同于
const x = Symbol();

不过我们知道,相同参数的Symbol.for()方法会返回相同的 Symbol 值。TypeScript 目前无法识别这种情况,所以可能出现多个 unique symbol 类型的变量,等于同一个 Symbol 值的情况。

const a:unique symbol = Symbol.for('foo');
const b:unique symbol = Symbol.for('foo');

unique symbol 类型的一个作用,就是用作属性名,这可以保证不会跟其他属性名冲突。如果要把某一个特定的 Symbol 值当作属性名,那么它的类型只能是 unique symbol,不能是 symbol。

const x:unique symbol = Symbol();
const y:symbol = Symbol();interface Foo {[x]: string; // 正确[y]: string; // 报错
}

上面示例中,变量y当作属性名,但是y的类型是 symbol,不是固定不变的值,导致报错。

unique symbol类型也可以用作类(class)的属性值,但只能赋值给类的readonly static属性。

class C {static readonly foo:unique symbol = Symbol();
}

上面示例中,静态只读属性foo的类型就是unique symbol。注意,这时staticreadonly两个限定符缺一不可,这是为了保证这个属性是固定不变的。

区别

在 TypeScript 中,Symbol 类型本身已经是唯一的标识符,这意味着每次调用 Symbol() 都会创建一个唯一的符号。然而,TypeScript 引入了 unique symbol 类型来进一步加强类型系统的能力,特别是在涉及常量和类型安全的场景中。

Symbolunique symbol 的区别

  • Symbol:
    • 每次调用 Symbol() 创建的符号是唯一的,但它们没有类型区分。
    • 符号本身无法用于声明独特的常量类型。
  • unique symbol:
    • unique symbol 是一种具备类型层面唯一性的符号,通常与 const 结合使用。
    • 可以用作常量标识符,以确保唯一性,并且这种唯一性反映在类型系统中。

为什么需要 unique symbol

  1. 常量标识符的类型安全:
    • unique symbol 允许创建具有类型唯一性的常量标识符,确保类型检查期间的唯一性。例如,在定义常量时,使用 unique symbol 可以确保每个常量都有一个唯一的类型。
  2. 类型系统中的唯一性:
    • 在复杂的类型系统中,尤其是涉及到映射、键值对等场景时,unique symbol 可以作为键,以确保类型安全和唯一性。

以下是一些示例,展示了 unique symbol 的使用场景及其优势:

常量标识符的类型安全

// 使用 unique symbol 创建常量标识符
const UNIQUE_KEY: unique symbol = Symbol("unique_key");// 定义一个包含 unique symbol 作为键的对象类型
interface MyObject {[UNIQUE_KEY]: string;
}// 创建对象并赋值
const obj: MyObject = {[UNIQUE_KEY]: "This is a unique value"
};// 尝试访问键值
console.log(obj[UNIQUE_KEY]); // 输出: This is a unique value

在上述示例中,UNIQUE_KEY 是一个具有唯一类型的常量标识符。这确保了在类型系统中,该键是唯一的,并且不会与其他符号混淆。

类型系统中的唯一性

const KEY1: unique symbol = Symbol("key1");
const KEY2: unique symbol = Symbol("key2");interface MyMap {[KEY1]: number;[KEY2]: string;
}const myMap: MyMap = {[KEY1]: 123,[KEY2]: "abc"
};console.log(myMap[KEY1]); // 输出: 123
console.log(myMap[KEY2]); // 输出: abc

在这个例子中,我们定义了两个 unique symbol 类型的键 KEY1KEY2,并在 MyMap 接口中使用它们。这样可以确保 KEY1KEY2 在类型系统中是唯一的,不会发生冲突。

unique symbol 在 TypeScript 中的引入,主要是为了增强类型系统的能力,确保在常量标识符和复杂类型系统中具有唯一性和类型安全。通过使用 unique symbol,开发者可以创建具有唯一类型的常量标识符,确保在类型检查期间不会发生冲突。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/28337.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解释双向队列(Deque)的概念,Java 中的 ArrayDeque 和 LinkedList 作为 Deque 的实现,它们各自有什么优缺点?

双向队列(Deque,全称为 Double Ended Queue)是一种具有队列和栈特性的数据结构,允许在两端进行元素的添加和移除操作。这意味着你可以在队列的前端(头部)或后端(尾部)进行入队&#…

从 Acme.Sh V3.0 说说 ZeroSSL

熟悉明月的都知道,明月一直都在使用 acme.sh 作为服务器端申请、部署、续期免费 SSL 证书的主要工具,今天在帮一个站长申请 SSL 证书的时候发现 acme.sh v3.0 开始默认的免费 SSL 证书变更为:ZeroSSL 了,这个 ZeroSSL 其实跟明月一…

在 C++ 中使用不同平台的时间函数及比较

在 C 编程中,时间函数的选择对于性能测量、任务调度和时间戳记录至关重要。不同的操作系统提供了不同的时间函数,同时在同一个平台上,也可能有多种不同的时间函数可供选择。本文将介绍在 C 中常用的时间函数,并比较它们在不同平台…

通俗范畴论2 有向图与准范畴

退一步海阔天空,在正式进入范畴论之前,我们可以重新审视一下我们是如何认识世界的,有了这个对人类认识世界过程的底层理解,可以帮助我们更好地理解范畴论。 对于人类认识世界,最神奇的一点就是这个世界居然是可以认识…

map文件分析

以下是一个具体的map文件示例,并附上详细的描述,帮助你更好地理解如何读取和分析map文件: 示例map文件 Memory ConfigurationName Origin Length Attributes FLASH 0x08000000 0x0…

初识docker插件

文章目录 一、Docker插件概述二、Docker插件的优势三、Docker插件的使用例子1. 安装Docker插件2. 启用Docker插件3. 创建卷并使用 四、常用的Docker插件五、总结 Docker插件(Docker Plugin)是Docker扩展功能的一种重要方式,它允许用户为Docke…

Elasticsearch 认证模拟题 - 22

一、题目 索引 task 索引中文档的 fielda 字段内容包括了 hello & world,索引后,要求使用 match_phrase query 查询 hello & world 或者 hello and world 都能匹配该文档 1.1 考点 分词器 1.2 答案 # 创建符合条件的 task 索引,…

C++之 delete删除拷贝构造函数和拷贝赋值运算符

在 C 中,删除拷贝构造函数和拷贝赋值运算符是一种常见的方法,用于防止对象的拷贝和赋值。这在某些情况下是必要的,例如当类管理资源(如线程、文件句柄或网络连接)时,以确保资源的唯一性和避免潜在的资源泄漏…

算法人生(22):从“生成对抗网络”看“逆商提升”

​ 在图像生成与编辑、音频合成、视频生成领域里,有一个非常重要的深度学习方法——生成对抗网络(简称GANs),它是由两个神经网络组成的模型,分别为生成器(Generator)和判别器(Discr…

【Linux】I/O多路复用

文章目录 I/O多路复用select()select()缺点 poll()poll()缺点 epoll()LT(水平触发模式)ET(边缘触发模式)具体函数 I/O多路复用 多进程和多线程实现并发会消耗大量的资源,主进程/线程用于监听和接受连接,再创建多个子进程/子线程来完成与连接的各个客户端…

采煤vr事故灾害应急模拟救援训练降低生命财产损失

在化工工地,设备繁多、环境复杂,潜藏着众多安全隐患,稍有不慎便可能引发安全事故。为了保障工地的安全,我们急需一套全面、高效的安全管理解决方案。web3d开发公司深圳华锐视点研发的工地安全3D模拟仿真隐患排查系统,正…

可以用来制作硬模空心耳机壳的胶粘剂有哪些种类?

可以用来制作硬模空心耳机壳的胶粘剂有哪些种类? 制作耳机壳的胶粘剂有很多种类,常见的有环氧树脂胶水、UV树脂胶、快干胶、热熔胶等。 这些胶粘剂都有不同的特点和适用场景,可以根据自己的需求选择合适的类型。 例如: 环氧树脂…

css3新增伪类有哪些?

在 CSS3 中引入了一些新的伪类,用于向选择器添加特定的状态或行为。以下是一些常见的 CSS3 新增的伪类: :nth-child() 和 :nth-of-type():根据元素在其父元素中的位置选择元素。例如,:nth-child(odd) 选择所有奇数位置的子元素。 …

pdf转图片,pdf转图片在线转

pdf转图片的方法,对于许多人来说可能是一个稍显陌生的操作。然而,在日常生活和工作中,我们有时确实需要将pdf文件转换为图片格式,以便于在特定的场合或平台上进行分享、展示或编辑。以下,我们将详细介绍一个pdf转成图片…

用宝塔部署vue+springboot上线公网详细步骤

首先自己在腾讯云中按照教程安装好宝塔。这是宝塔面板,获取登录宝塔的网址和账号密码。 1.在navicat新建数据库 如果出现权限问题,可以在宝塔数据库面板phpMyAdmin中进行权限设置 navicat可以修改用户权限 2.在宝塔面板新建数据库 3.将前端打包的dist文件…

linux 部署瑞数6实战(维普,药监局)第一部分

声明 本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!wx 本文章未经许可禁止转载&…

【星海随笔】云解决方案学习日志篇(二) kafka、Zookeeper、Fielbeat

Elastic 中国社区官方博客 https://blog.csdn.net/ubuntutouch/category_9209092.html Kafka kafka的源代码是基于Scala语言编写的,运行在Java虚拟机(即:JVM)上。因此,在安装kafka之前需要先安装JDK Kafka 为什么依赖 Zookeepe…

52. QT插件开发--插件程序(带ui文件)的创建与编译

1. 说明 一般情况下,针对代码量比较小的QT程序不需要进行插件集成化开发,但是针对大型程序来说,代码结构比较复杂,使用插件开发的方式可以提高代码开发和维护效率,团队之间的分工合作也会更加的明确。所谓插件式开发,实际上就是把程序的一部分功能封装起来,编译成一个单…

一血c++

题目描述 每一个竞赛选手都无法拒绝拿一血 "一血"其实就是同学们在榜单上看到的深绿色的标记,代表着某道题目,他是第一个通过的。 叶苡朋老师是一名资深信奥选手,在大学多次获奖,也是一个资深抢一血爱好者&#xff0…

认识Redis 主从同步、事务和Memcached的区别

08- 什么是 Redis 主从同步? Redis 的主从同步(replication)机制,允许 Slave 从 Master 那里,通过网络传输拷贝到完整的数据备份,从而达到主从机制。 主数据库可以进行读写操作,当发生写操作的时候自动将数据同步到从…