TS中的一些符号

一、! 非空断言操作符

在上下文中当类型检查器无法断定类型时,一个新的后缀表达式操作符 ! 可以用于断言操作对象是非 null 和非 undefined 类型。具体而言,x! 将从 x 值域中排除 null 和 undefined
那么非空断言操作符到底有什么用呢?下面我们先来看一下非空断言操作符的一些使用场景。

  • 忽略 undefined 和 null 类型
// 监听div大小控制元素显示与隐藏
const [divSize, setDivSize] = useState<number | undefined>(window.innerWidth);
const handleChange = ()=> {
	setDivSize(document.getElementById('targetDiv')?.offsetWidth)
}
useEffect(()=>{
	// 监听
	window.addEventListener("resize", handleChange);
	// 销毁
    return () => window.removeEventListener("resize", handleChange);
}, [])


<div style={{width: '100%'}} id="targetDiv">
	// 如果不加!,会报错,对象可能为“未定义”。
	{divSize! > 1000 ? && <span>哈哈哈</span>} 
</div>
  • 调用函数时忽略 undefined 类型
type HandleChange= () => void;

function myFunc(onChange: HandleChange | undefined) {
	//如果不加!,会报错
	const a = onChange(); // Error
  	const b = onChange!(); //OK
}
  • 确定赋值断言

在 TypeScript 2.7 版本中引入了确定赋值断言,即允许在实例属性和变量声明后面放置一个 ! 号,从而告诉 TypeScript 该属性会被明确地赋值。

let x: number;
initialize();
// 在赋值前使用了变量“x”。
console.log(2 * x); // Error

function initialize() {
  x = 10;
}

很明显该异常信息是说变量 x 在赋值前被使用了,要解决该问题,可以使用确定赋值断言:

let x!: number;
initialize();
console.log(2 * x); // Ok

function initialize() {
  x = 10;
}

二、?. 运算符

TypeScript 3.7 实现可选链,如果遇到 null 或 undefined 就可以立即停止某些表达式的运行。
?. 与 && 运算符行为略有不同,&& 专门用于检测 false 值,比如空字符串、0、NaN、null 和 false 等。而 ?. 只会验证对象是否为 null 或 undefined,对于 0 或空字符串来说,并不会出现 “短路”。

  • 在使用可选调用的时候,我们要注意以下两个注意事项

1.如果存在一个属性名且该属性名对应的值不是函数类型,使用 ?. 仍然会产生一个 TypeError 异常。

2.可选链的运算行为被局限在属性的访问、调用以及元素的访问 —— 它不会沿伸到后续的表达式中,也就是说可选调用不会阻止 a?.b / someMethod() 表达式中的除法运算或 someMethod 的方法调用。

三、?? 空值合并运算符

TypeScript 3.7 引入空值合并运算符 ??,当左侧操作数为 null 或 undefined 时,其返回右侧的操作数,否则返回左侧的操作数。

与逻辑或 || 运算符不同,逻辑或会在左操作数为 false 值时返回右侧操作数。

console.log(false || '哈哈哈')  // 哈哈哈
console.log(false ?? '哈哈哈')  // false
  • 不能与 && 或 || 操作符共用

如果??和&&或||共用了会抛出 SyntaxError。

// 但当使用括号来显式表明优先级时是可行的,
(null || undefined ) ?? "foo"; // 返回 "foo"

四、?: 可选属性

比如定义了一个子组件的属性为value和onChange,在主组件使用的时候只用了value属性,就会报错,这个时候就可以使用?:,比如

type Person = {
	name: string
	age?: number
}

将属性变成可选的,就不会报错啦

五、& 运算符

在 TypeScript 中交叉类型是将多个类型合并为一个类型。通过 & 运算符可以将现有的多种类型叠加到一起成为一种类型,它包含了所需的所有类型的特性。

type Animal = { age: number; };
type Dog= Animal & { name: string; };

let tony: Dog = {
  age: 2,
  name: '旺财'
}
  • 同名基础类型属性的合并

那么现在问题来了,假设在合并多个类型的过程中,刚好出现某些类型存在相同的成员,但对应的类型又不一致,比如:

interface X {
  c: string;
  d: string;
}

interface Y {
  c: number;
  e: string
}

type XY = X & Y;
type YX = Y & X;

let p: XY;
let q: YX;

p = {c: 6, d: '111', e: '222'} // Error

在上面的代码中,接口 X 和接口 Y 都含有一个相同的成员 c,但它们的类型不一致。对于这种情况,此时 XY 类型或 YX 类型中成员 c 的类型是不是可以是 string 或 number 类型呢?并不是!既是string又是number的类型是不存在的,所以c的类型是never。

六、| 分隔符

在 TypeScript 中联合类型(Union Types)表示取值可以为多种类型中的一种,联合类型使用 | 分隔每个类型。联合类型通常与 null 或 undefined 一起使用

  • 类型保护

当使用联合类型时,我们必须尽量把当前值的类型收窄为当前值的实际类型,而类型保护就是实现类型收窄的一种手段。类型保护是可执行运行时检查的一种表达式,用于确保该类型在一定的范围内。

七、_ 数字分隔符

TypeScript 2.7 带来了对数字分隔符的支持,正如数值分隔符 ECMAScript 提案中所概述的那样。对于一个数字字面量,你现在可以通过把一个下划线作为它们之间的分隔符来分组数字:

const inhabitantsOfMunich = 1_464_301;
const distanceEarthSunInKm = 149_600_000;
const fileSystemPermission = 0b111_111_000;
const bytes = 0b1111_10101011_11110000_00001101;

分隔符不会改变数值字面量的值,但逻辑分组使人们更容易一眼就能读懂数字

  • 使用限制

虽然数字分隔符看起来很简单,但在使用时还是有一些限制。比如你只能在两个数字之间添加 _ 分隔符,也不能连续使用多个 _ 分隔符。

  • 解析分隔符

解析数字的函数是不支持分隔符:

Number('123_456') // NaN
parseInt('123_456') // 123
parseFloat('123_456') // 123

// 可以借用正则表达式来解析
let str = '123_456'
console.log(str.replace(/[^0-9]/gu,'')) //123456

八、TypeScript 断言

类型断言好比其他语言里的类型转换,但是不进行特殊的数据检查和解构。它没有运行时的影响,只是在编译阶段起作用。
类型断言有两种形式:

  • “尖括号” 语法
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;
  • as 语法
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;

九、#XXX 私有字段

在 TypeScript 3.8 版本就开始支持 ECMAScript 私有字段

1.私有字段以 # 字符开头,有时我们称之为私有名称;
2.每个私有字段名称都唯一地限定于其包含的类;
3.不能在私有字段上使用 TypeScript 可访问性修饰符(如 public 或 private);
4.私有字段不能在包含的类之外访问,甚至不能被检测到。

class Person {
	#name: string
    constructor(name: string){
		this.#name = name
	}
  a(){
    console.log(this.#name)
  }
}

let person = new Person('名字');
console.log(person.#name); // Property '#name' is not accessible outside class 'Person' because it has a private identifier.
console.log(person.a()); //名字

参考文献:https://juejin.cn/post/6875091047752400910

  • 9
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值