TypeScript中的一些小技巧

本博客 hjy-xh,转载请申明出处

为什么通常来说类型声明的使用优先于类型断言

:类型声明更够更有效地帮助我们进行类型检查

假设有如下定义:

1
2
3
interface Person {
name: string;
}

当需要声明一个该类型变量时,可以有两种做法

1
2
3
4
5
6
7
const student_1: Person = {
name: 'John',
}

const student_2 = {
name: 'Tom'
} as Person

在常规情况下声明变量类型,优先使用第一种方式,这样能够帮助我们进行类型检查,这种错误提示显然是非常有用的,而使用断言时,有可能出现某个属性并不在断言的类型中的情况,这种情况下并没有报错

1
2
3
4
5
6
7
8
9
const student_3: Person = {
name: 'John',
age: 10 // 报错:“age”不在类型“Person”中
}

const student_4 = {
name: 'John',
age: 10 // ok
} as Person

类型断言只会影响 TypeScript 编译时的类型,类型断言语句在编译结果中会被删除,虽然最终转化出来的js能够运行正常,但这也会让同事感到迷惑

什么时候使用类型断言?

:只有你比TypeScript知道得更多的时候

举个🌰:

1
<button class="submit-btn">登录</button>
1
const el = document.querySelector('.sign-confirm-button')! as HTMLButtonElement;

由于TypeScript并不能访问到DOM,而作为开发者的我们,明确知道此处是一个按钮,这里就可以合理地断言成HTMLButtonElement,而非自动推断的Element | null

为什么尽量不使用包装类型

  • string 和 String

  • number 和 Number

  • boolean 和 Boolean

  • symbol 和 Symbol

  • bigint 和 BigInt

string举例,当我们在在字符串字面量上访问诸如 charAt 之类的方法时,JavaScript 将其包装在一个 String 对象中,调用该方法,然后丢弃该对象:

1
2
3
4
5
6
7
8
const originalCharAt = String.prototype.charAt;
String.prototype.charAt = function(pos) {
console.log(this, typeof this, pos);
return originalCharAt.call(this, pos);
};
console.log('primitive'.charAt(3));
//String {'primitive'} 'object' 3
// m

字符串和字符串对象不相等:

1
2
3
"John" === "John"; // true
"John" === new String("John"); // false
new String("John") === new String("John"); // false

在 TypeScript 中,可以将字符串基本类型 string 赋值给包装类型 String,但无法反过来将 String 赋值给 string

1
2
3
4
5
6
7
8
function getNameLength(studentName: String) {
return studentName.length; // ok
}
getNameLength('John')

function isStudent(studentName: String) {
return ['Jack', 'John'].includes(studentName); // 报错:类型“String”的参数不能赋给类型“string”的参数
}

运行时的值仍然是原始值,而不是对象,但是 TypeScript 允许这些声明,因为原始类型可以分配给对象包装器,这样看起来有些迷惑,所以最好统一使用原始类型