TS是JS的超集,比JS特性更多,使用起来更方便。TS不能直接在浏览器中运行,他需要先编译为JS,这个编译过程会检查类型错误,并将TS特有的语法转换为纯JS。

入门

第一个TS程序

以下是ts的一些特点:

  • .ts程序需要被编译tsc后变成.js代码才能使用。
  • ts区分大小写
  • 分号是可选的

变量

变量类型

这里只记录ts相对于c#特别的变量类型:

类型 描述 示例
number 表示数字,包括整数和浮点数 let age: number = 30;
boolean 表示布尔值true或false let isDone: boolean = true;
array 表示相同类型的元素数组 let list: number[] = [1, 2, 3];
tuple 表示已知类型和长度的数组 let person: [string, number] = ["Alice", 30];
any 任意类型,不进行类型检查 let value: any = 42;
undefined 表示未定义 let undef: undefined = undefined;
union 联合类型,表示可以是多种类型之一 let value: number | string;
unknown 不确定类型,需类型检查后再使用 let value: unknown = "Hello";
string 字符串

ts支持模板字符串,用反引号来定义,允许在字符串中插入变量或表达式,非常适合多行文本和拼接变量。

1
2
let name: string = "Alice";
let greeting:string = `Hello, ${name}! Welcom to TS!`;

number 数字

TypeScript 使用 number 表示所有数字,包括整数和浮点数。

any 类型

以表示任何类型。适合不确定数据类型的情况,但使用时需谨慎,因为 any 会绕过类型检查。

1
2
let randomValue: any = 42;
randomValue = "Hello";

任意值是 TypeScript 针对编程时类型不明确的变量使用的一种数据类型,它常用于以下三种情况。

  1. 变量的值会动态改变时,比如来自用户的输入,任意值类型可以让这些变量跳过编译阶段的类型检查,示例代码如下:
1
2
3
let x: any = 1;    // 数字类型
x = 'I am who I am'; // 字符串类型
x = false; // 布尔类型
  1. 改写现有代码时,任意值允许在编译时可选择地包含或移除类型检查,示例代码如下:
1
2
3
let x: any = 4;
x.ifItExists(); // 正确,ifItExists方法在运行时可能存在,但这里并不会检查
x.toFixed(); // 正确
  1. 定义存储各种类型数据的数组时,示例代码如下:
1
2
let arrayList: any[] = [1, false, 'fine'];
arrayList[1] = 100;

变量声明

声明

1
var [变量名] : [类型] = 值;

例如:

1
var uname: string = "Runoob";

声明变量的类型,但没有初始值,变量值会设置为 undefined:

1
var [变量名] : [类型];

例如:

1
var uname:string;

断言

  • 类型断言

类型断言可以用来手动指定一个值的类型,即允许变量从一种类型更改为另一种类型。
仅仅是“欺骗编译器”,运行时真实的数据、内存里的值完全不会发生任何变化。

语法格式:

1
<类型>值

或:

1
值 as 类型
  • 非空断言操作符
1
StartPage : Node = null!;

这句话的意思就是告诉TS:这个变量绝对不会是null/ undefined,不用给报空警告。

类型推断

当类型没有给出时,TS编译器会进行类型推断;如果由于缺乏声明而不能推断出类型,默认视作any类型。

运算符

基本和C#一样,有几个特殊的说一下:

  • 负号运算符
1
2
3
4
var x : number = 4;
var y = -x;
console.log("x的值为:", x); // 输出结果为4
console.log("y的值为:", y); // 输出结果为-4
  • 字符串连接运算符(+)

循环结构

  • for循环
1
2
3
for ( i = 1; i <= 10; i++ ){
// 内部逻辑
}
  • for…in循环
1
2
3
for (var val in list) { 
//语句
}

val 需要为 string 或 any 类型。

for-in拿到的是键名,比如"0", "1", "2"

  • for…of循环:适合遍历
1
2
3
4
let someArray = [1, "string", false]; 
for (let entry of someArray) {
console.log(entry); // 1, "string", false
}

for-of拿到的是数据本身

  • while循环
1
2
3
4
while(condition)
{
statement(s);
}
  • do-while循环
1
2
3
4
do
{
statement(s);
}while( condition );

函数

基本语法

  • 无参无返回值
1
2
3
4
function function_name()
{
// 执行代码
}

JS/TS 中,函数不写 return,函数执行完毕默认返回 undefined。

  • void:TS 类型,表示函数不需要使用返回值。函数体内可以写return;(不带值)。

  • undefined:JS 运行时真实的值。不写 return,调用函数得到的就是undefined。

  • 无参有返回值

1
2
3
function greet():string { // 返回一个字符串 
return "Hello World"
}
  • 有参有返回值
1
2
3
function add(x: number, y: number): number { 
return x + y;
}

参数

可选参数

在 TypeScript 函数里,如果我们定义了参数,则我们必须传入这些参数,除非将这些参数设置为可选,可选参数使用问号标识 ?。

以下实例,我们将 lastName 设置为可选参数:

1
2
3
4
5
6
7
8
9
10
function buildName(firstName: string, lastName?: string) { 
if (lastName)
return firstName + " " + lastName;
else
return firstName;
}

let result1 = buildName("Bob"); // 正确
let result2 = buildName("Bob", "Adams", "Sr."); // 错误,参数太多了
let result3 = buildName("Bob", "Adams"); // 正确

默认参数

1
2
3
4
function calculate_discount(price:number,rate:number = 0.50) {
var discount = price * rate;
console.log("计算结果: ",discount);
}

剩余参数

有一种情况,我们不知道要向函数传入多少个参数,这时候我们就可以使用剩余参数来定义。

剩余参数语法允许我们将一个不确定数量的参数作为一个数组传入。

函数的最后一个命名参数 restOfName 以 ... 为前缀,它将成为一个由剩余参数组成的数组,索引值从0(包括)到 restOfName.length(不包括)。

1
2
3
4
5
function buildName(firstName: string, ...restOfName: string[]) { 
return firstName + " " + restOfName.join(" ");
}

let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");

匿名函数

1
2
3
var res = function(a:number,b:number) { 
return a*b;
};

匿名函数自调用在函数后使用 () 即可:

1
2
3
4
(function () {
var x = "Hello!!";
console.log(x)
})()

构造函数

TS也支持JS内置的构造函数 Function() 来定义函数:

1
2
3
var myFunction = new Function("a", "b", "return a * b"); // 最后一个参数是一个含有包括函数定义的 JavaScript 语句的字符串
var x = myFunction(4, 3);
console.log(x); // 输出结果是12

Lambda函数(箭头函数)

1
var foo = (x:number):number => 10 + x console.log(foo(100)) //输出结果为 110

函数重载

重载是方法名字相同,而参数不同,返回类型可以相同也可以不同。

每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。

进阶

装饰器

装饰器(Decorators)是 TypeScript 的一项实验性功能。

它允许开发者在不修改原类的情况下,采用 @ 符号作为语法糖,为类、方法、属性或参数添加额外的功能。

装饰器本质上是一个函数,它可以在运行时被调用,以修改目标对象的行为。

  1. 配置启用装饰器

在使用装饰器之前,需要在 TypeScript 配置文件 tsconfig.json 中启用相关编译选项。

tsconfig.json配置:

1
2
3
4
5
6
7
8
9
{
"compilerOptions": {
// 启用装饰器语法
"experimentalDecorators": true,

// 启用装饰器元数据
"emitDecoratorMetadata": true
}
}
  1. 装饰器类型

装饰器包括类装饰器、方法装饰器、访问器装饰器、属性装饰器。

下面列举常用的装饰器:

  • 可在Inspector窗口编辑
1
@property({ type : Node })
  • @property:装饰器标记
  • type: Node:指定这个属性的类型是节点 Node