第二章:TypeScript核心语法速通
好,咱们直接进入正题。TypeScript 说白了就是给 JavaScript 穿了一层盔甲。你在鸿蒙开发里写 ArkTS,本质上就是在写 TypeScript 的超集。所以这一章,我把最常用的几个语法点给你捋一遍。
2.1 变量声明:let 和 const
我个人习惯,能用 const 的地方绝不用 let。为什么?因为代码里变量越少变化,你脑子要记的东西就越少。
// 这样写,我心里踏实
const maxRetryCount = 3;
const apiBaseUrl = 'https://api.example.com';
// 只有明确需要改变的值,才用 let
let currentPage = 1;
let timerId: number | null = null;
我在项目中遇到过一个问题:有人用 var 声明了一个循环变量,结果回调里拿到的全是最后一个值。嗯,这就是 var 的函数作用域在捣鬼。let 和 const 是块级作用域,完美避坑。
2.2 基础类型:number / string / boolean
这三个类型是基本功。你想想看,鸿蒙应用里哪个页面能离开它们?
// 数字:整数、浮点数、NaN、Infinity 都归它管
const price: number = 29.9;
const count: number = 100;
// 字符串:单引号双引号都行,我习惯用单引号
const userName: string = '张三';
const greeting: string = `你好,${userName}!`; // 模板字符串真香
// 布尔值:true / false
const isLogin: boolean = false;
const isVIP: boolean = true;
我曾经踩过一个坑:从接口拿到的数据,明明应该是数字,结果因为 JSON 解析问题变成了字符串。然后我用 === 比较死活不相等。所以现在我对类型转换特别敏感。
Number() 或 parseInt() 做显式转换,别依赖隐式转换。隐式转换有时候像开盲盒。
2.3 数组:Array
数组在鸿蒙开发里太常用了。列表数据、表单选项、缓存队列……到处都是它。
// 两种写法,我推荐第一种
const fruits: string[] = ['苹果', '香蕉', '橘子'];
const numbers: Array<number> = [1, 2, 3]; // 泛型写法,也行
// 只读数组:防止意外修改
const readonlyList: readonly string[] = ['a', 'b', 'c'];
// readonlyList.push('d'); // 这行会报错,编译器不让你改
为什么要有只读数组?我在项目里遇到过同事不小心 push 了一个不该 push 的数据,导致列表渲染错乱。从那以后,只要是不该变的数组,我都加上 readonly。
2.4 枚举:enum
枚举这东西,说白了就是给一组常量起个有意义的名称。你写代码的时候不用记数字,记名字就行。
// 数字枚举:默认从 0 开始
enum Status {
Pending, // 0
Processing, // 1
Completed, // 2
Failed // 3
}
// 字符串枚举:每个值都要手动赋值
enum HttpMethod {
GET = 'GET',
POST = 'POST',
PUT = 'PUT',
DELETE = 'DELETE'
}
// 使用
const currentStatus: Status = Status.Processing;
console.log(currentStatus); // 输出 1
我个人习惯用字符串枚举。为什么?因为调试的时候打印出来是 'GET' 而不是 0,一眼就能看懂。数字枚举在日志里看到 0、1、2,你还得回去翻定义,多麻烦。
2.5 函数定义与箭头函数
函数是 TypeScript 的核心。鸿蒙里你写的每个页面组件、每个事件处理,本质上都是函数。
2.5.1 普通函数
// 有返回值
function add(a: number, b: number): number {
return a + b;
}
// 无返回值:用 void
function logMessage(msg: string): void {
console.log(msg);
// 没有 return
}
// 可选参数:用 ?
function greet(name: string, greeting?: string): string {
return `${greeting || '你好'},${name}`;
}
可选参数要注意:它必须放在必选参数后面。这是 TypeScript 的规则,也是常识——你想想看,如果可选参数在前面,调用的时候编译器怎么知道哪个参数被跳过了?
2.5.2 箭头函数
箭头函数我太喜欢了。它简洁,而且没有自己的 this。这在鸿蒙的组件回调里特别有用。
// 基本写法
const double = (x: number): number => x * 2;
// 多行函数体需要花括号和 return
const processData = (data: string[]): string[] => {
const result = data.filter(item => item.length > 0);
return result.map(item => item.trim());
};
// 在数组方法里用箭头函数,真香
const numbers = [1, 2, 3, 4, 5];
const evenNumbers = numbers.filter(n => n % 2 === 0);
// 结果:[2, 4]
我曾经在项目里看到有人把箭头函数和普通函数混着用,结果 this 指向乱成一锅粥。我的建议是:在类的方法里用普通函数,在回调、数组方法、事件处理里统一用箭头函数。这样最不容易出错。
new myArrowFunc(),TypeScript 会直接报错。嗯,这是设计如此,箭头函数天生就不是干这个的。
2.6 类型推断与类型注解
TypeScript 很聪明,很多时候你不用写类型,它能自己推断出来。
// 类型推断:TypeScript 知道 name 是 string
const name = '鸿蒙开发';
// 等价于:const name: string = '鸿蒙开发';
// 复杂情况还是写注解更安全
function fetchData(): Promise<UserInfo> {
// 这里显式声明返回类型,调用方一目了然
return api.get('/user');
}
我个人习惯:简单变量靠推断,函数参数和返回值一定写注解。为什么?因为函数是代码的接口,接口清晰了,整个项目才不会乱。
2.7 小结
这一章的内容,说白了就是 TypeScript 的「最小可用集」。你掌握了 let/const、基础类型、数组、枚举、函数和箭头函数,就已经能写大部分鸿蒙页面了。
下一章我们会深入接口和类型别名,那才是 TypeScript 真正发力的地方。到时候你会看到,类型系统能帮你省多少 bug。