Bootstrap

TypeScript入门


前言

TypeScript 可以看成是 JavaScript 的超集,它在继承了后者全部语法的基础上进行了扩展。通过类型注解显式指定变量的类型,TypeScript可以在编写代码的同时发现代码中的错误。


一、基础类型

在TypeScript中可以通过varletconst声明变量,但为避免作用域和重复定义等问题,通常使用letconst进行变量声明。

let x = 10;
let y: undefined = undefined;
// const用于声明常量,其值在初始化后不可改变
const z: number = 20;

二、变量声明

TypeScript在继承了JavaScript数据类型的基础上进行了新增,以下是常用的数据类型:

  1. boolean:表示逻辑值,true 和 false
let isDone: boolean = false;
  1. number:表示数字,整数和小数
const z: number = 20;
  1. string:使用单引号 ' 或双引号 " 来表示字符串,使用反引号定义多行文本和内嵌表达式
let year: string = "2024年";
let words: string = `您好,今年是 ${ year }`;
  1. 数组 Array:number[ ] 或使用数组泛型 Array<元素类型>
let list: number[] = [1, 2, 3];
let list2: Array<number> = [1, 2, 3];

list.push(4) // 末尾追加
list.unshift(0) // 在开头插入 0 1 2 3 4
list.pop() // 删除末位 0 1 2 3
list.splice(0,1) // 从第几位删除几个 1 2 3
list.shift() // 删除首位 2 3
list = list.concat(list2) // 连接两个数组 
list.indexOf(3) // 搜索元素第一次出现的位置
list.sort() // 排序
list.reverse() // 反转数组顺序
  1. 元组 Tuple:表示已知元素数量和类型的数组,每个位置的类型固定
let x: [string, number];
x = ['hello', 10]; // 正确
x = [10, 'hello']; // 错误
  1. 枚举 enum:定义数值集合,相当于用于存放一系列相关常量的容器
enum Color {Red, Green, Blue}
let c: Color = Color.Red; // 0 默认情况下从0开始编号

enum Color {Red = 1, Green = 2, Blue = 4} // 也可以手动指定成员的值
  1. any:声明为 any 的变量可以赋予任意类型的值
let x: any = 4;
x= "maybe a string instead";
  1. void:表示没有类型,通常用于表示函数没有返回值
function hello(): void {
    console.log("hello");
}
  1. null:表示对象值缺失
let x: null = null
  1. undefined:用于初始化变量为一个未定义的值
let x: undefined = undefined
  1. never:任何类型的子类型,表示永不存在的值
  2. object:表示非原始类型
let obj: object = {};

三、条件和循环

1.条件语句

  • if…else if…else
if(num > 0) { 
    console.log(num+" 是正数") 
} else if(num < 0) { 
    console.log(num+" 是负数") 
} else { 
    console.log(num+" 不是正数也不是负数") 
}
  • switch…case
switch(grade) { 
    case "red": { 
        console.log("红"); 
        break; 
    } 
    case "green": { 
        console.log("绿"); 
        break; 
    } 
    default: { 
        console.log("非法输入"); 
        break;              
    } 
}
  • 三目运算符:Test ? expr1 : expr2
    如果条件语句 Test 返回 true 则返回 expr1,返回 false 则返回 expr2
var result = 5 > 0 ? 1 : 2
console.log(result) // 1 

2.循环语句

  • for 循环
for(let i = 5;i>=1;i--) {
   console.log(i);
}
  • for…in 循环 和 for…of 循环
// for..in 遍历索引
let list:any="abc"
for(let i in list) { 
    console.log(i)       //0 1 2
    console.log(list[i]) //a b c
}
// for..of 遍历元素
let list= [1, "string", false];
for (let x of list) {
    console.log(x); // 1, "string", false
}
  • while 循环 和 do…while 循环
let num=5
while(num >=1) {  
    num--; 
    console.log(num)// 4 3 2 1 0
} 

let n=5
do { 
    console.log(n); // 5 4 3 2 1
    n--; 
} while(n>=1);

四、函数

TypeScript中可指定函数的参数类型及返回值的类型。返回值类型可以省略,TypeScript会自动推断。

  • 普通函数
    function 函数名 (参数1:参数类型, 参数2: 参数类型): 函数返回类型{ }
function add (number1:number, number2: number): number {
    return number1 + number2
}
  • 匿名函数
    匿名函数指没有函数名的函数,可以赋值给变量,这种表达式即函数表达式
const add2=function(number1:number, number2: number): number{
	return number1 + number2
}
  • 箭头函数
    const 函数名 = (参数1:参数类型, 参数2: 参数类型): 函数返回类型 => { }
const add3 = (number1:number, number2: string): string => {
    return number1 + number2
}
  • 参数
    • 可选参数:可传可不传,在参数名后使用 ? 实现
    • 默认参数:带默认值的参数
    • 剩余参数:参数数量不确定
function mySlice(start:number,end?:number):void {
    console.log("开始:" + start + '结束' + end )
}

function mySlice(start:number,end = 5):void {
    console.log("开始:" + start + '结束' + end )
}

function buildName(firstName: string, ...restOfName: string[]) {
    return firstName + " " + restOfName.join(" ");
}

五、类

  • 类是一种用户定义的数据类型,它拥有属性和方法。
  • TypeScript中通过 class 定义类,使用 new 进行实例化。static 用于定义静态成员(属性和方法),这些成员存在于类本身,通过类名.xxx进行调用。
class Animal {
	static words: string = "这是一个Animal类"
    name: string;
	//构造函数
    constructor(name: string) {
        this.name = name;
    }

	static test(): void {
        console.log(Animal.words);
    }
    speak(): void {
        console.log(`${this.name} makes a noise.`);
    }
    
}

let dog = new Animal('Buddy');
dog.speak(); // Buddy makes a noise.
Animal.test(); // 这是一个Animal类
  • 继承
    • TypeScript 一次只能继承一个类,不支持继承多个类,类继承使用关键字 extends
    • 重写:子类可以对父类的方法重新定义,其中 super 关键字是对父类的引用。
class Dog extends Animal {
    speak() {
        super.speak();// 调用父类的函数
        console.log('Woof! Woof!');
    }
}

let dog = new Dog('Buddy');
dog.speak() // Buddy makes a noise.  Woof! Woof!
  • 抽象类
    • 抽象类本身不可以被实例化,可以被继承,作为其他派生类的基类使用且派生类必须对其中的抽象方法进行实现。
    • abstract 定义抽象类和在抽象类内部定义抽象方法。
abstract class Animal {
    abstract makeSound(): void;
    move(): void {
        console.log('roaming the earch...');
    }
}
  • 封装
    • TypeScript中通过访问修饰符和getters/setters的设置,对类进行封装。
    • public: 默认,公有,可以在任何地方被访问。
    • protected: 受保护,可以被其自身以及其子类访问。
    • private: 私有,只能被其定义所在的类访问。
class Person {
    private _age: number;

    constructor(age: number) {
        this._age = age;
    }
	set age(age: number) {
        this._age = age;
    }
    get age(): number {
        return this._age;
    }
}

let person = new Person(30);
person.age = 20
console.log(person.age); // 20

六、接口

  • 接口使用 interface 定义,使用 implements 实现,一个类可以同时实现多个接口。
interface Wolf {
	attack(): void;
}

class WolfMan extends Person implements Wolf {
	attack(){
        console.log("attack")
    }
}

let p1=new WolfMan("Ben");
p1.attack()

七、模块

通常代码会根据需要拆分成多个文件,即所谓的模块。定义在模块里面的变量、函数和类等在模块外部是不可见的,需要用 export 导出。相应地,可以通过 import 进行导入。

// myModule.ts
export function sayHello(name: string) {
    return "Hello, " + name;
}
// main.ts
import { sayHello } from './myModule';
console.log(sayHello("World"));

八、泛型

泛型允许在定义函数、类、接口等时使用占位符来表示类型,而不是具体的类型。

function identity<T>(arg: T): T {
    return arg;
}

let output = identity<string>("myString"); // 类型参数是 string
let output2 = identity(42); // 编译器自动推断出 T 是 number
;