TypeScript 是一种 JavaScript 的超集,它在语言层面提供了静态类型检查等特性,更加适用于大型项目开发。TypeScript 的学习过程中,会遇到一些需要注意的问题,在这篇文章中,我们会详细探讨这些问题以及如何避免它们。
1. Type 和 interface 的区别
在 TypeScript 中,我们可以使用 type
和 interface
关键字来定义一个自定义类型,这些自定义类型的作用类似于 C++ 中的类型定义。
-- -------------------- ---- ------- ---- ------ - - ----- ------- ---- ------- - --------- ------ - ----- ------- ---- ------- -
那么这两者有何不同呢?其实,type
和 interface
的最大区别在于它们对于相同名称的类型定义的处理方式。
如果我们同时定义了一个 type
和一个 interface
,且它们的名称相同但是定义不同,那么 TypeScript 会默认将它们合并为一个类型,但这种合并方式并不总是符合预期。
-- -------------------- ---- ------- ---- ------ - - ----- ------- - --------- ------ - ---- ------- - -- ---- ------ --------- --------- ------ - ----- ------- ---- ------- -
因此,在实际开发中,建议避免同时使用 type
和 interface
定义相同名称的类型。
2. 泛型中使用 extends
关键字
在 TypeScript 中,我们可以使用泛型来提高代码复用性,同时也可以使用 extends
关键字来约束泛型参数的类型。
function getLength<T extends { length: number }>(value: T): number { return value.length; } getLength('hello'); // 5 getLength([1, 2, 3]); // 3 getLength({ length: 3 }); // 3
使用 extends
关键字的泛型有一些约束条件,其中最常见的就是约束参数类型必须拥有 length
属性。但是,在实际开发中,有时候我们需要针对多个属性进行约束,这时候可以使用交叉类型(&
)来进行联合约束。
function getValue<T extends { name: string } & { age: number }>(value: T): string { return `${value.name} is ${value.age} years old`; } getValue({ name: 'Ming', age: 18 }); // 'Ming is 18 years old'
3. 脑补非空断言 !
在 TypeScript 中,我们可以使用 !
符号来表示一个变量不可能为 null
或 undefined
,这在实际开发中可以提高代码的可读性和安全性。
-- -------------------- ---- ------- -------- ---------------- - ----- ------ -- - ------- - ------ --------- - ------ --- - -------- ---------------- - ----- ------ - - ---- - ---------- - ------ ---------- -
但是,对于一些没有进行过类型检查的变量,盲目使用 !
符号进行非空断言会导致类型错误的发生。
const inputElement = document.querySelector('input'); const inputValue = inputElement!.value;
上述代码中,我们使用 !
符号断言了 inputElement
的非空,但是如果页面中没有 <input>
元素,那么此时 inputElement
会被赋值为 null
,使用 !
符号进行非空断言会引发类型错误,提倡在对非空断言进行使用的时候,需要考虑到应用的场景。
4. 类型推导和类型注释
在 TypeScript 中,我们可以使用类型注释或类型推导来确定变量或函数的类型,这两种方式都有它们的优缺点,我们需要根据实际场景进行选择。
let str: string = 'hello'; // 类型注释 let num = 100; // 类型推导 function add(a: number, b: number): number { // 类型注释 return a + b; } const multiply = (a: number, b: number) => a * b; // 类型推导
使用类型注释时,可以在定义变量或函数的同时明确指定类型,使代码更加规范易读。但是,在复杂的类型声明中,手动书写类型会变得十分繁琐,这时候可以使用类型推导的方式。
-- -------------------- ---- ------- --------- ---- - ----- ------- ---- ------- -------- - ------- ------- ----- ------- - - ----- ----- ---- - - ----- ------- ---- --- -------- - ------- -------- ---- -------- ----- ---------- - --
5. 对于联合类型的处理
在 TypeScript 中,我们可以使用联合类型(|
)来表示一个变量可能拥有的多种类型。
function getLength(value: string | number) { if(typeof value === 'string') { return value.length; } else { return value.toString().length; } }
但是,联合类型在实际开发中也常常成为类型错误的原因之一,特别是在涉及到类型转换的场景下。
function getLength(value: string | number) { return value.length; // 类型错误:数字类型没有 length 属性 }
因此,在联合类型的处理中,我们需要仔细分析实际场景,合理使用类型断言或者类型保护来避免类型错误的发生。
function getLength(value: string | number) { if(typeof value === 'string') { return value.length; } else { return value.toString().length; } }
总结
在 TypeScript 的学习过程中,需要注意一些细节问题,例如 type
和 interface
的区别、泛型中使用 extends
关键字、脑补非空断言 !
、类型推导和类型注释、对于联合类型的处理等。只有在深入理解这些问题的基础上,才能更加熟练地运用 TypeScript 的各种特性。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64eefdecf6b2d6eab38fd862