暮年|细数这些年被困扰过的 TS 问题( 七 )


该行为是由按位运算引起的 。 有时 SomeFlag.Foo | SomeFlag.Bar 用于生成另一个 SomeFlag 。 相反 , 你最终得到的是数字 , 并且你不想强制回退到 SomeFlag 。
了解完上述内容 , 我们再来看一下 let value: Fonum = 12; 这个语句 , 该语句 TS 编译器不会报错 , 是因为数字 12 是可以通过 Fonum 已有的枚举成员计算而得 。
let value: Fonum =Fonum.a << Fonum.b << Fonum.a |Fonum.a << Fonum.b; // 12 继续阅读:5000 多字 , 让你一文掌握 TS 枚举九、使用 # 定义的私有字段与 private 修饰符定义字段有什么区别在 TypeScript 3.8 版本就开始支持 ECMAScript 私有字段 , 使用方式如下:
class Person {#name: string;constructor(name: string) {this.#name = name;}greet() {console.log(`Hello, my name is ${this.#name}!`);}}let semlinker = new Person("Semlinker");semlinker.#name;//~~~~~// Property '#name' is not accessible outside class 'Person'// because it has a private identifier.与常规属性(甚至使用 private 修饰符声明的属性)不同 , 私有字段要牢记以下规则:

  • 私有字段以 # 字符开头 , 有时我们称之为私有名称;
  • 每个私有字段名称都唯一地限定于其包含的类;
  • 不能在私有字段上使用 TypeScript 可访问性修饰符(如 public 或 private);
  • 私有字段不能在包含的类之外访问 , 甚至不能被检测到 。
说到这里使用 # 定义的私有字段与 private 修饰符定义字段有什么区别呢?现在我们先来看一个 private 的示例:
class Person {constructor(private name: string){}}let person = new Person("Semlinker");console.log(person.name);在上面代码中 , 我们创建了一个 Person 类 , 该类中使用 private 修饰符定义了一个私有属性 name , 接着使用该类创建一个 person 对象 , 然后通过person.name 来访问 person 对象的私有属性 , 这时 TypeScript 编译器会提示以下异常:
Property 'name' is private and only accessible within class 'Person'.(2341)那如何解决这个异常呢?当然你可以使用类型断言把 person 转为 any 类型:
console.log((person as any).name);通过这种方式虽然解决了 TypeScript 编译器的异常提示 , 但是在运行时我们还是可以访问到 Person 类内部的私有属性 , 为什么会这样呢?我们来看一下编译生成的 ES5 代码 , 也许你就知道答案了:
var Person = /** @class */ (function () {function Person(name) {this.name = name;}return Person;}());var person = new Person("Semlinker");console.log(person.name);这时相信有些小伙伴会好奇 , 在 TypeScript 3.8 以上版本通过 # 号定义的私有字段编译后会生成什么代码:
class Person {#name: string;constructor(name: string) {this.#name = name;}greet() {console.log(`Hello, my name is ${this.#name}!`);}}以上代码目标设置为 ES2015 , 会编译生成以下代码:
"use strict";var __classPrivateFieldSet = (this}privateMap.set(receiver, value);return value;};var __classPrivateFieldGet = (this}return privateMap.get(receiver);};var _name;class Person {constructor(name) {_name.set(this, void 0);__classPrivateFieldSet(this, _name, name);}greet() {console.log(`Hello, my name is ${__classPrivateFieldGet(this, _name)}!`);}}_name = new WeakMap();通过观察上述代码 , 使用 # 号定义的 ECMAScript 私有字段 , 会通过 WeakMap 对象来存储 , 同时编译器会生成 __classPrivateFieldSet 和 __classPrivateFieldGet 这两个方法用于设置值和获取值 。


推荐阅读