第4章 ArkTS语言基础(上):语法概览、变量声明与数据类型

好,咱们正式开始接触ArkTS了。说实话,很多从Java或标准TypeScript转过来的朋友,第一眼看到ArkTS会觉得「有点怪」。嗯,我当初也是这个感觉。但用了一段时间后,你会发现它其实是在帮你规避一些容易踩坑的写法。

这一章我们先打地基。把语法概览、变量声明、基础数据类型和函数定义这几个核心点讲透。你想想看,地基打不牢,后面写复杂页面和业务逻辑的时候,debug能把你搞疯。

4.1 ArkTS语法概览:它到底「严」在哪?

ArkTS是TypeScript的超集,但做了严格的静态类型约束。说白了,它不允许你随心所欲地写JS那种「爱啥类型就啥类型」的代码。

核心原则就两条:

  • 类型必须明确:变量、参数、返回值,都得说清楚是什么类型。
  • 运行时行为可预测:不允许隐式类型转换,减少运行时意外。

我在项目中遇到过最典型的例子:有个同事从JS转过来,写了个 let count = "5" + 3,在JS里结果是 "53",但在ArkTS里直接编译报错。为什么?因为类型不匹配。ArkTS不允许string和number直接相加。这种严格其实是在保护你,避免线上出现诡异的bug。

重要认知: ArkTS不是「阉割版」的TS,而是「安全增强版」。它去掉了一些容易出问题的动态特性,换来了更好的编译期检查和性能优化空间。

4.2 变量声明:let 和 const 怎么选?

在ArkTS里,声明变量只有两个关键字:letconst。没有 var,这一点跟现代TS保持一致。

我的选择原则很简单:

  • 默认用 const:只要这个变量在初始化后不需要重新赋值,就用const。这能避免很多意外修改。
  • 只有明确需要重新赋值时,才用 let:比如循环计数器、累加器这类场景。

我曾经在一个项目里看到有人把所有变量都声明成 let,结果一个函数里变量被改了七八次,最后查bug查了整整一下午。从那以后,我团队里就定了个规矩:能用const绝不用let。

个人习惯: 我写ArkTS代码时,会先写const,如果编译报错说「不能赋值给常量」,再改成let。这样能强制自己思考「这个变量真的需要变吗?」

看个例子:

// 推荐写法
const userName: string = "张三";
const maxRetryCount: number = 3;

// 需要重新赋值的场景
let currentIndex: number = 0;
for (let i = 0; i < 10; i++) {
  currentIndex = i;
}

4.3 基础数据类型:string, number, boolean

这三个是最常用的基础类型。没什么花哨的,但有几个细节要注意。

string(字符串)

支持单引号、双引号和模板字符串。我个人偏爱模板字符串,因为拼接变量时最直观。

const firstName: string = "李";
const lastName: string = "四";
// 模板字符串,用反引号
const fullName: string = `${firstName}${lastName}`;
console.log(fullName); // 输出:李四

注意: ArkTS里字符串是不可变的。你没法通过索引修改某个字符。比如 str[0] = 'a' 这种操作是不允许的。想修改?重新生成一个新字符串吧。

number(数字)

ArkTS里只有一种数字类型:number。它涵盖整数和浮点数。没有Java里那种int、float、double的区分。

const age: number = 25;
const price: number = 19.99;
const hexValue: number = 0xFF; // 十六进制也支持

我记得有个新手问我:「为什么我算钱的时候,0.1 + 0.2 不等于 0.3?」嗯,这是所有编程语言都有的浮点数精度问题。ArkTS也不例外。如果你要做精确的金额计算,建议用整数(分)来算,或者用专门的库。

boolean(布尔值)

只有 truefalse 两个值。注意,ArkTS里不会做隐式类型转换。你不能写 if (1) 这种代码,必须写成 if (1 === 1) 或者 if (true)

const isLoggedIn: boolean = false;
// 正确写法
if (isLoggedIn === true) {
  // 执行逻辑
}
// 错误写法(编译报错)
// if (isLoggedIn) { }  // 这样写其实可以,但为了清晰,我建议显式比较

避坑指南: 我曾经在条件判断里直接写 if (someString),在JS里空字符串会被当作false。但在ArkTS里,这种写法虽然能编译通过,但语义不清晰。我后来统一改成 if (someString.length > 0),代码可读性提升了一大截。

4.4 复合数据类型:array 和 object

基础类型只能存单个值。要存一组数据,就得用数组和对象。

array(数组)

数组有两种声明方式。我个人推荐使用泛型写法,更清晰。

// 方式一:泛型写法(推荐)
const names: Array<string> = ["张三", "李四", "王五"];

// 方式二:简写语法
const ages: number[] = [25, 30, 35];

// 混合类型?不行!ArkTS要求数组元素类型一致
// const mixed: Array<string | number> = ["hello", 123]; // 联合类型可以,但别滥用

数组的操作方法和标准JS一样:pushpopforEachmap 等都能用。但注意,如果你声明的是 const 数组,你不能重新赋值整个数组,但可以修改数组里的元素。

const fruits: string[] = ["苹果", "香蕉"];
fruits.push("橘子"); // 可以,修改内容
// fruits = ["西瓜"]; // 报错!不能重新赋值

object(对象)

对象在ArkTS里需要定义结构。你可以用接口(interface)或类型别名(type)来约束对象的形状。

// 先定义接口
interface User {
  id: number;
  name: string;
  isVIP: boolean;
}

// 然后创建对象
const user: User = {
  id: 1,
  name: "赵六",
  isVIP: true
};

// 访问属性
console.log(user.name); // 赵六

我的经验: 定义对象时,一定要先写接口或类型。别偷懒直接写 const obj = {} 然后往里塞属性。ArkTS的静态检查会帮你发现拼写错误和类型不匹配。我见过太多因为属性名写错导致的bug了。

4.5 函数定义:从基础到进阶

函数是ArkTS里组织逻辑的基本单元。写法上跟TS很像,但约束更严格。

基本函数定义

必须指定参数类型和返回值类型。如果函数没有返回值,用 void

// 有返回值
function add(a: number, b: number): number {
  return a + b;
}

// 无返回值
function logMessage(msg: string): void {
  console.log(msg);
  // 没有 return 语句
}

可选参数和默认参数

参数可以设为可选(加问号),也可以给默认值。

// 可选参数
function greet(name: string, greeting?: string): string {
  if (greeting) {
    return `${greeting}, ${name}`;
  }
  return `你好, ${name}`;
}

// 默认参数
function createUser(name: string, age: number = 18): object {
  return { name, age };
}

console.log(createUser("小明")); // { name: '小明', age: 18 }

注意: 可选参数必须放在必选参数后面。这是语法规定,也是常识——你想想看,如果可选参数在前面,调用时传参顺序就乱套了。

箭头函数(Lambda表达式)

箭头函数在ArkTS里非常常用,尤其是在回调场景。写法简洁,而且不绑定自己的 this

// 传统函数
const double1 = function(n: number): number {
  return n * 2;
};

// 箭头函数(推荐)
const double2 = (n: number): number => n * 2;

// 多行箭头函数
const processData = (data: string[]): number => {
  const filtered = data.filter(item => item.length > 3);
  return filtered.length;
};

我记得刚开始用箭头函数时,总觉得语法别扭。但用顺手之后,发现它特别适合用在数组的 mapfilter 方法里,代码一下子简洁了很多。

函数作为参数(回调函数)

ArkTS里函数是一等公民,可以像变量一样传递。

// 定义回调类型
type Callback = (result: string) => void;

// 接受回调的函数
function fetchData(url: string, onSuccess: Callback): void {
  // 模拟网络请求
  const data = "模拟数据";
  onSuccess(data);
}

// 调用时传入箭头函数
fetchData("https://api.example.com", (result) => {
  console.log("获取到数据:", result);
});

核心要点: 函数定义时,参数类型和返回值类型必须写清楚。这不仅是语法要求,更是文档。三个月后你回头看自己的代码,类型声明就是最好的注释。

4.6 本章小结

这一章我们覆盖了ArkTS最基础但最重要的几个概念:

  • 语法风格:严格静态类型,不允许隐式转换
  • 变量声明:优先用 const,必要时用 let
  • 基础类型:string、number、boolean,注意精度和不可变性
  • 复合类型:数组元素类型一致,对象要定义接口
  • 函数定义:类型明确,善用箭头函数和回调

这些内容看起来简单,但它们是后面所有复杂逻辑的基石。下一章我们会深入讲联合类型、类型别名和泛型,那才是真正体现ArkTS威力的地方。

嗯,先消化这些。有任何疑问,欢迎在课程群里讨论。咱们下章见。