Typescript初入门笔记1 | 青训营笔记

79 阅读7分钟

1 TypeScript简介

1.1 简介

Typescript 是一种由微软开发的开源编程语言,它是 JavaScript 的超集,意味着它包含 JavaScript 的所有语法和特性,并且还提供了更多的工具和方法来帮助开发者更好地构建大型应用程序。Typescript 的目的是通过添加类型注解、类、接口等概念来增强 JavaScript 的可读性和可维护性,从而使代码更加健壮、易于维护和重构。

1.2 TypeSciprt 和Javascript的区别

1.3 为什么使用TYpescript

  • 可读性增强:基于语法解析TSDoc,ide增强
  • 可维护性增强:在编译阶段暴露大部分错误----多人合作的大型项目中,获得更好的稳定性和开发效率

2 TypeScript基本类型

2.1基本类型

数据类型关键字描述
任意类型any声明为 any 的变量可以赋予任意类型的值。
数字类型number双精度 64 位浮点值。它可以用来表示整数和分数。
let binaryLiteral: number = 0b1010; // 二进制
let octalLiteral: number = 0o744; // 八进制
let decLiteral: number = 6; // 十进制
let hexLiteral: number = 0xf00d; // 十六进制
字符串类型string一个字符系列,使用单引号(')或双引号(")来表示字符串类型.
反引号(```)来定义多行文本和内嵌表达式。
let name: string = "Runoob"; <br>let years: number = 5; <br>let words: string = 您好,今年是 name发布{ name } 发布 { years + 1} 周年;
布尔类型boolean表示逻辑值:true 和 false。
let flag: boolean = true;
数组类型声明变量为数组。
// 在元素类型后面加上[]
let arr: number[] = [1, 2]; <br>// 或者使用数组泛型
let arr: Array<number> = [1, 2];
元组元组类型用来表示已知元素数量和类型的数组,
各元素的类型不必相同,对应位置的类型需要相同。

let x: [string, number]; <br>x = ['Runoob', 1]; // 运行正常 <br>x = [1, 'Runoob']; // 报错 <br>console.log(x[0]); // 输出 Runoob
枚举enum枚举类型用于定义数值集合。

enum Color {Red, Green, Blue}; <br>let c: Color = Color.Blue; <br>console.log(c); // 输出 2
voidvoid用于标识方法返回值的类型,表示该方法没有返回值。

function hello(): void { alert("Hello Runoob"); }
nullnull表示对象值缺失,NUll在Javascript中是表示一个空对象引用,用 typeof 检测 null 返回是 object,是其他任何类型(包括 void)的子类型
undefinedundefined用于初始化变量为一个未定义的值,Undefined,undefined 是一个没有设置值的变量。typeof 一个没有值的变量会返回 undefined,是其他任何类型(包括 void)的子类型
nevernevernever 是其它类型(包括 null 和 undefined)的子类型,代表从不会出现的值。

2.2 高级类型

2.2.1 联合类型|

联合类型(Union Types)是 TypeScript 中的一种高级类型,它允许一个变量的类型可以是多个类型之一。使用联合类型可以更灵活地定义变量,提高代码的可复用性和可读性。例如,一个变量可以是字符串或数字或布尔值中的任意一种类型。

function printId(id: number | string) {
  console.log(`ID is ${id}`);
}

printId(101); // Output: ID is 101
printId("202"); // Output: ID is 202

变量、函数参数、函数返回值等位置

2.2.2 交叉类型&

交叉类型(Intersection Types)是 TypeScript 中的一种高级类型,它允许将多个类型合并为一个类型。使用交叉类型可以创建一个包含多个类型特征的新类型,这个新类型包含了所有交叉类型的特征。例如,可以将两个接口合并成一个新接口,这个新接口包含了两个接口的所有属性和方法。

interface Person {
  name: string;
  age: number;
}

interface Employee {
  companyId: number;
  department: string;
}

type EmployeeInfo = Person & Employee;

在上面的例子中,我们定义了两个接口 PersonEmployee,然后使用交叉类型将它们合并成一个新类型 EmployeeInfo。新类型包含了两个接口的所有属性和方法,这样可以方便地创建一个包含多个类型特征的新类型。

2.2.3 类型断言

类型断言(Type Assertion)是 TypeScript 中的一种语法,它允许开发者手动指定一个值的类型。使用类型断言可以在编译时绕过 TypeScript 的类型检查,将一个值强制转换为指定的类型。类型断言有两种语法格式:一种是使用尖括号 <>,另一种是使用 as 关键字。

let value: any = "hello world";
let length1: number = (<string>value).length;
let length2: number = (value as string).length;

在上面的例子中,我们将一个字符串类型的变量 value 赋值给了一个 any 类型的变量。然后我们使用类型断言将 value 强制转换为字符串类型,并获取它的长度。 需要注意的是,类型断言不是类型转换,它只在编译时起作用,不会影响运行时的类型。因此,在使用类型断言时需要确保断言的类型是正确的,否则可能会导致运行时错误

2.2.4 类型别名type

类型别名(Type Alias)是 TypeScript 中的一种高级类型,它允许为一个类型起一个新的名字。使用类型别名可以方便地定义复杂的类型,提高代码的可读性和可维护性。

3 函数类型

3.1函数特点

  • TS定义函数类型时候,需要指出输入参数的类型和输出类型
  • 支持函数重载,即名称相同,但是参数不同

3.2函数语法:

//return_type 是返回值的类型
//param1、param2 为参数名。
//datatype 为参数类型。
function function_name( param1 [:datatype], param2 [:datatype]):return_type { 
    // 语句
    return value; 
}

3.3函数示例:

  • 求两数之和,形参列表中指出了输入类型是number,输出类型是number
function add(num1: number, num2: number): number {
    return num1 + num2;
}

3.4函数重载示例

function reverse(string: string): string;
function reverse<T>(array: T[]): T[];
function reverse(stringOrArray: string | any[]): string | any[] {
    if (typeof stringOrArray === 'string') {
        return stringOrArray.split('').reverse().join('');
    } else {
        return stringOrArray.slice().reverse();
    }
}

3.5剩余参数

当我们不确定要向函数中传入多少个参数的时候,这时我们可以使用剩余参数来进行定义,剩余参数语法允许我们将一个不确定数量的参数作为一个数组传入。

function buildName(firstName: string, ...restOfName: string[]) {
    return firstName + " " + restOfName.join(" ");
}
  
let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");
  • 同时TS也支持使用递归函数、Lambda函数表达式、匿名函数、函数默认参数等来进行函数的编写。

4 接口

4.1什么是接口

接口是一个可选的类型,用于描述对象的形状。接口定义了对象应该具有的属性和方法,这些方法都应该是抽象的,需要由具体的类去实现,然后第三方就可以通过这组抽象方法调用,让具体的类执行具体的方法。

4.2接口的使用

使用接口需要使用interface指定会使用到的属性和方法,不需要重写就可以使用接口定义的属性和方法,只要对象的形状与接口定义的形状匹配即可。

接口的使用示例:

interface Animal {
    name: string;
    age: number;
    isPet: boolean;
    makeSound(): void;
}

class Cat implements Animal {
    name: string;
    age: number;
    isPet: boolean;

    constructor(name: string, age: number, isPet: boolean) {
        this.name = name;
        this.age = age;
        this.isPet = isPet;
    }

    makeSound() {
        console.log('Meow!');
    }
}

const myCat = new Cat('Fluffy', 2, true);
console.log(myCat.name);
myCat.makeSound();

该接口定义了一个 Person 对象应该具有的三个属性:firstName、lastName 和 age。printPerson 函数接受一个 Person 对象作为参数,并打印出其完整姓名和年龄。

该接口定义了一个 Animal 对象应该具有的四个属性:nameageisPetmakeSound 方法。Cat 类实现了 Animal 接口,并实现了 makeSound 方法。myCat 对象是 Cat 类的一个实例,它具有 nameage 属性,并可以调用 makeSound 方法。

在此示例中,我们定义了一个 Animal 接口,该接口具有 nameageisPetmakeSound 方法。然后,我们定义了一个 Cat 类,该类实现了 Animal 接口,并实现了 makeSound 方法。最后,我们创建了一个 myCat 对象,它是 Cat 类的一个实例,并打印出了其 name 属性和调用了其 makeSound 方法。

4.3 接口中的数组

接口中我们可以将数组的索引值和元素设置为不同类型,索引值可以是数字或字符串。

interface namelist { 
   [index:number]:string 
} 
var list2:namelist = ["Google","Runoob","Taobao"]

该段代码定义了一个 namelist 接口,该接口定义了一个索引签名[index: number]: string 表示定义了一个索引签名,其中索引是数字类型,值是字符串类型。然后,我们声明了一个 list2 变量,并将其指定为 namelist 类型。我们可以将 list2 变量设置为一个字符串数组,由于该数组符合 namelist 接口中定义的形状,因此不会出现编译错误。