typescript(上)--个人学习笔记

227 阅读16分钟

TS的学习

TS大部分知识点在于JS,所以只记录一些TS特有的知识点

TS的中文网

官网网址
bootcss.comTypeScript 中文手册
tslang.cnTypeScript中文网
nodejs.cnTypeScript 手册

降级编译

ts一般直接默认ES6的代码

"target":"es2016"

但是不是所有的浏览器都支持ES6的,所以要一个降级编译,这样ts会把一些语法降级编译成老版的js 在tsconfig.json文件里更改

"target":"es5"

严格模式

在tsconfig.json文件里更改

"strict":true,
"noImplicAny":true,
"strictNullChecks":true

strict

当设置为true时,TypeScript编译器会启用严格模式。这意味着编译器会对代码中的潜在问题进行更严格的检查,以提高代码质量和可维护性。启用严格模式会同时启用以下三个选项: "noImplicitAny", "strictNullChecks", "strictFunctionTypes"。

noImplicitAny

当设置为true时,TypeScript编译器会禁止隐式的any类型。在代码中,如果没有为变量指定显式的类型,编译器将会报错。这对于避免潜在的类型错误非常有用,因为any类型会绕过类型检查,可能导致意外的行为和错误。

strictNullChecks

当设置为true时,TypeScript编译器会对null和undefined进行严格的类型检查。这意味着变量的类型不能包含null或undefined,除非明确地声明为允许这些值的联合类型。这有助于避免null引用错误和undefined的意外使用。

字面量,常量和变量

在JavaScript中,字面量、常量和变量是编程中的基础概念。

字面量 (Literals)

字面量是在源代码中直接表示值的方式。这些值可以是数字、字符串、布尔值、对象、数组等。

  • 数字字面量:423.14
  • 字符串字面量:'Hello'"World"
  • 布尔字面量:truefalse
  • 对象字面量:{key: 'value'}
  • 数组字面量:[1, 2, 3]

常量 (Constants)

在JavaScript中,常量是值在初始化后就不能再改变的变量。在ES6(ECMAScript 2015)之前,JavaScript并没有真正的常量,通常我们使用全部大写的变量名来模拟常量。但从ES6开始,我们有了const关键字来声明常量。

例如:

	const PI = 3.14159;  
	// PI = 3.14; // 这行会抛出错误,因为PI是一个常量

注意:使用const声明的对象或数组的值本身不能重新赋值,但它们的属性或元素是可以改变的。

变量 (Variables)

变量是可以存储任何类型数据的命名容器。在JavaScript中,我们使用let(从ES6开始)或var(在ES6之前)来声明变量。变量和常量中存的是值内存地址,不是直接保存值。

例如:

	let name = 'Alice';  
	name = 'Bob'; // 可以重新赋值  
	  

	var age = 25;  
	age = 30; // 也可以重新赋值
  • var声明的变量具有函数作用域或全局作用域,而let声明的变量具有块级作用域(即在一对大括号{}内)。
  • 在同一个作用域内,let不允许重复声明同一个变量,而var则允许。
  • var存在变量提升(hoisting)现象,而let不会。

通常推荐使用let而不是var,因为它提供了更清晰的作用域规则和更少的错误可能性。

变量的内存图

js变量的后面跟的是地址值,该地址上放具体的内容值。这样可以防止数据过长

Java变量后面能直接放内容值,因为Java有类型,定义类型就确定了值的大小,不怕数据过长

Ts和Java很像,但是他最终是编译成js,所以ts虽然有类型,但是内存模型还是js一样

TS的数据类型

ts具有一定的只能推导类型的能力,但是一般推荐手动声明

最基本的三个

判断值的类型的typeof

// 数值类型
let a:number = 10;
let binaryLiteral: number = 0b1010; //二进制
let octalLiteral: number = 0o744;//八进制
let hexLiteral: number = 0xf00d; //十六进制
//数值是以二进制保存的,超出就会被截断,数值类型和bigint不能直接运算

//布尔类型
let b:boolean = true;

//字符串类型,用单引号或双引号或反单引号来包括
//字符串中一般为了打印一些特别字符,要用上反斜杠
let s:string = "hello";
let s1:string=`${a}`

两个新类型:bigint和symbol

在TypeScript中,bigint和symbol是两种特殊的数据类型。

bigint:大整形是一种用于表示超过Number.MAX_SAFE_INTEGER(最大安全整数)的整数的数据类型。大整形可以通过在数字后面添加n或使用BigInt()函数来声明。例如:

const bigIntValue: bigint = 9007199254740991n;
const anotherBigIntValue = BigInt(9007199254740991);

需要注意的是,大整形不能与普通整数进行直接运算。如果要进行运算,需要先将其转换为大整形。例如:

const result = bigIntValue + BigInt(10);

Symbol(符号):Symbol是一种原始数据类型,用于表示唯一的标识符。Symbol的值是唯一且不可变的,可以用作对象属性的键。Symbol可以通过Symbol()函数来创建。就类似一个随机数,例如:

const sym1 = Symbol();
const sym2 = Symbol('mySymbol');

需要注意的是,由于Symbol的值是唯一的,因此无法通过直接比较来判断两个Symbol是否相等。可以使用Symbol.for()来创建可重用的Symbol,或使用Symbol.keyFor()来获取Symbol的键。例如:

const sym1 = Symbol.for('mySymbol');
const sym2 = Symbol.for('mySymbol');
console.log(sym1 === sym2); // true

const key = Symbol.keyFor(sym1);
console.log(key); // 'mySymbol'

any类型

//就相当于原生的js,它可以是任何类型
let any1:any = 10;
any1 = "hello";

unknown类型


//unknown类型只能赋值给自身和any,其他的类型都不能接收它
//unknown类型的值,其的属性和方法都不能调用,因为它一切未知
let unknown1:unknown = 10;
unknown1 = "hello";

Object类型

在 TypeScript 中,有两种表示对象类型的方式:Object 和 object。

  1. Object 类型

    • Object 是JavaScript中所有对象的基类。它不是基本类型(primitive type),而是引用类型(reference type)。
    • 使用 Object 类型可以创建具有任意属性和方法的对象。
    • 你可以通过点符号(.)或方括号([])来访问或修改对象的属性。
  2. 基本类型(Primitive Types)

    • 基本类型包括:NumberStringBooleanSymbolnull、和 undefined
    • 这些值是不可变的,并且是按值传递的。
  3. 内置类型(Built-in Types)

    • JavaScript中的所有数据类型,包括基本类型和引用类型,都可以被视为内置类型。
  4. object(小写)

    • object(小写)通常指的是JavaScript中任意对象类型的通用类型标识符。在typeof运算符的上下文中,它会返回非基本类型(如数组、函数、日期对象等)的值作为"object"。但是,这并不意味着所有的对象都是Object类型的实例。例如,数组不是Object的直接实例,但它们是继承自Object.prototype的。
  5. 访问对象的属性

    • 你可以使用点符号(.)或方括号([])来访问或修改对象的属性。例如:

      javascript复制代码
      	let obj = { name: 'Alice', age: 30 };  
      
      	console.log(obj.name); // 输出 "Alice"  
      
      	console.log(obj['age']); // 输出 30
      

总结:

  • 使用 Object 类型(注意大写)可以创建和操作具有属性和方法的对象。
  • 使用 object(小写)通常是在 typeof 运算符的上下文中,用来表示一个非原始值。但是,这并不表示一个具体的类型,只是一个通用的分类。

object类型

TS (TypeScript) 中的对象类型有以下几种:

  1. object:表示任意对象类型,可以包含任意属性和方法。
let obj: object = {
  name: 'John',
  age: 25
};
  1. any:表示任意类型,可以赋值给任何类型的变量。
let anyObj: any = {
  name: 'John',
  age: 25
};
  1. 声明对象的属性和方法:
let person: {
  name: string;
  age: number;
  sayHello: () => void;
} = {
  name: 'John',
  age: 25,
  sayHello: () => {
    console.log('Hello!');
  }
};
  1. 接口:定义对象的形状,指定属性和方法的类型。
interface Person {
  name: string;
  age: number;
  sayHello: () => void;
}

let person: Person = {
  name: 'John',
  age: 25,
  sayHello: () => {
    console.log('Hello!');
  }
};
  1. 类:用类来创建对象,并定义类的属性和方法。
class Person {
  name: string;
  age: number;

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

  sayHello() {
    console.log('Hello!');
  }
}

let person = new Person('John', 25);

类型大小写的区别

在 TypeScript 中,Number、String 和 Boolean 是 JavaScript 中的基本数据类型。它们与 TypeScript 中对应的小写形式 number、string 和 boolean 的区别如下:

  1. Number vs number:

    • Number 是 Number 对象的包装类,它包含了一些用于处理数字的方法和属性。在 TypeScript 中使用 Number 会得到一个对象。
    • number 是 TypeScript 中的关键字,用于表示数字类型。
  2. String vs string:

    • String 是 String 对象的包装类,它包含了一些用于处理字符串的方法和属性。在 TypeScript 中使用 String 会得到一个对象。
    • string 是 TypeScript 中的关键字,用于表示字符串类型。
  3. Boolean vs boolean:

    • Boolean 是 Boolean 对象的包装类,它包含了一些用于处理布尔值的方法和属性。在 TypeScript 中使用 Boolean 会得到一个对象。
    • boolean 是 TypeScript 中的关键字,用于表示布尔类型。

在实际使用中,一般推荐使用 number、string 和 boolean 这些小写形式的关键字来表示对应的基本数据类型,而不是使用 Number、String 和 Boolean 这些包装类。因为使用关键字更加简洁,而且在类型判断和类型推断上也更加准确。

null,undefined类型

undefined未定义,栈中没分配位置,相当于没报名

null未赋值,栈中分配位置了,但是指向的堆中没有东西,相当于报名了,但是人没来,班里找不到这人,null是表示空对象的,所以用typeof来检测是object

void正常运行的无返回,一般用于函数方法中,相当于一个人去学校就住下了,不用回家

never不正常运行的无返回,一般用于函数方法中,相当于一个人去学校的路上失踪了,或者学校的路无限长,一直没到学校

let n:null = null;
let un:undefined = undefined;

默认情况下nullundefined是所有类型的子类型。 就是说你可以把 nullundefined赋值给number类型的变量。

然而,当你指定了--strictNullChecks标记,nullundefined只能赋值给void和它们各自。 这能避免 很多常见的问题。 也许在某处你想传入一个 stringnullundefined,你可以使用联合类型string | null | undefined

void类型

// 一般模式null能为void空值,但是在严格模式下,不能!!
// let v1:void = null; 
let v:void = undefined;

// void一般作为规定函数的返回值使用,一般不直接用于规定赋值类型

never类型

TypeScript中的never类型表示那些永远不会有返回值的类型。它通常用于表示函数的返回类型,以表明该函数抛出异常或永远不会返回。

例如,以下函数的返回类型被标注为never

function throwError(): never {
  throw new Error("An error occurred");
}

在这个例子中,throwError函数抛出一个异常,并且永远不会返回任何值。

另一个例子是never类型在类型推断中的使用:

function infiniteLoop(): never {
  while (true) {
    // do something
  }
}

在这个例子中,infiniteLoop函数是一个无限循环函数,它永远不会结束,因此它的返回类型被推断为never

never类型还可以用于处理联合类型的情况,当某个联合类型的所有成员都不能返回时,该联合类型的类型将被推断为never

总之,never类型用于表示不可能有任何返回值的情况,例如抛出异常或永远不会结束的循环。它在类型推断和函数返回类型中都有广泛的应用。

never和void

Void和Never都是在TypeScript中用于表示无值的类型,但它们之间有一些区别。

Void类型表示没有返回值的函数的返回类型,但是程序是正常执行到结束的,或者可以用于声明一个没有任何类型的变量。例如:

function doSomething(): void {
  console.log("This function doesn't return anything");
}

let variable: void;

复制插入

Never类型表示不会返回的函数的返回类型,或者可以用于表示永远不会发生的值的类型,程序可能停不下来,或则执行不下去。例如:

function throwError(): never {
  throw new Error("An error occurred");
}

function infiniteLoop(): never {
  while (true) {
    console.log("This loop runs forever");
  }
}

在上面的例子中,throwError函数抛出错误后会终止程序的执行,因此它的返回类型是neverinfiniteLoop函数会无限循环,永远不会结束,因此它的返回类型也是never

在使用上,Void类型应用的场景更多是在函数的返回类型上,表示函数没有任何返回值。Never类型则更多的用于函数永远不会返回的情况,比如抛出错误或者无限循环等。

总结一下:

  • Void类型表示没有返回值的函数的返回类型,或者可以用于声明一个没有任何类型的变量。
  • Never类型表示不会返回的函数的返回类型,或者可以用于表示永远不会发生的值的类型。

类型权限

由高向低

1.top type顶级类型:any unknown

2.Object

4.Number String Boolean

5.number string boolean

6.具体的值 1,“你好”,false

7.never

TS的数组

TS(TypeScript)是一种静态类型的编程语言,它支持数组的定义和使用。在TS中,可以使用以下方式定义数组:

数组

数组的两种写法

//普通的写法
type[]
//泛型的写法
Array<type>
let arr:number[] = [1,2,3]
let arr2:Array<number> = [1,2,3]

arr2=["2"]//这时候就会报错,因为数组类型已经定义为number,不能再给赋值为字符串的了
arr2=[2]//这是可以的
arr2=[]//这也是可以的

声明数组

  1. 声明一个数组变量并初始化:
let arr: number[] = [1, 2, 3, 4, 5];
  1. 使用Array关键字声明一个数组变量并初始化:
let arr: Array<number> = [1, 2, 3, 4, 5];
  1. 使用Array关键字声明一个数组变量并指定长度:
let arr: Array<number> = new Array(5);

注意:在TS中,数组的元素类型可以是任意类型,包括基本类型和自定义类型。例如:

let arr: string[] = ["a", "b", "c"];
let arr2: Array<boolean> = [true, false, true];
let arr3: Array<Person> = [person1, person2, person3];

以上是定义和初始化数组的方式,接下来可以使用下标访问数组元素,或使用数组的pushpopslice等方法对数组进行操作。

元组

元组是 TypeScript 中的一种数据类型,它允许你在一个变量中存储多个不同类型的值。元组在数组中使用下标来访问元素,而在元组中使用固定的位置来访问元素。

元组的定义使用类似数组的语法,但是需要指定每个元素的类型。例如,一个包含字符串和数字类型的元组可以这样定义:

let myTuple: [string, number] = ["Hello", 42];

这个元组的第一个元素是字符串类型,第二个元素是数字类型。

访问元组的元素可以使用下标,下标从 0 开始。例如,上面定义的元组可以这样访问:

console.log(myTuple[0]); // 输出: Hello
console.log(myTuple[1]); // 输出: 42

元组的长度是固定的,一旦定义不能改变。如果你尝试访问超过元组长度的下标,TypeScript 会给出一个编译时错误。

元组还可以包含可选元素,这些元素可以使用问号来表示。例如,下面的元组包含一个字符串和一个可选的数字:

let myTuple: [string, number?] = ["Hello"];

这个元组的第一个元素是字符串类型,第二个元素是可选的数字类型。访问可选元素时,需要进行判空操作,以避免出现 undefined。

元组还可以包含多个可选元素。例如,下面的元组包含一个字符串和两个可选的数字:

let myTuple: [string, number?, number?] = ["Hello", 42];

这个元组的第一个元素是字符串类型,第二个和第三个元素是可选的数字类型。访问可选元素时,同样需要进行判空操作。

元组还可以使用 rest 参数来处理可变长度的元组。例如,下面的元组包含一个字符串和任意个可选的数字:

let myTuple: [string, ...number[]] = ["Hello", 42, 43, 44];

这个元组的第一个元素是字符串类型,后面的元素是可变长度的数字类型。访问可变长度元组时,可以使用 for...of 循环遍历或者使用数组的各种方法进行操作。

总结一下,元组是一种特殊的数组类型,它可以在一个变量中存储多个不同类型的值,并通过固定的位置来访问这些值。元组的长度是固定的,一旦定义不能改变。元组还可以包含可选元素和可变长度的元素。

TS的枚举

在TypeScript中,枚举(enum)是一种有限集合的数据类型,它可以为一组相关的值定义一个命名的常量列表。枚举可以通过枚举成员的名称来引用其对应的值,使得代码更具可读性和可维护性。 枚举的定义语法如下:

enum EnumName {
    Member1,
    Member2,
    Member3,
    // ...
}

其中,EnumName是枚举的名称,Member1、Member2、Member3等是枚举成员的名称,每个枚举成员都可以有一个隐式的数字值,默认从0开始递增。例如,下面是一个表示星期几的枚举:

enum Weekday {
    Sunday,     // 0
    Monday,     // 1
    Tuesday,    // 2
    Wednesday,  // 3
    Thursday,   // 4
    Friday,     // 5
    Saturday    // 6
}

可以通过枚举成员的名称来获取其对应的值,例如Weekday.Monday的值为1。

枚举成员也可以手动指定其对应的值,例如:

enum Weekday {
    Sunday = 2,
    Monday ,
    Tuesday,
    Wednesday,
    Thursday,
    Friday ,
    Saturday,
}

此时,Weekday.Monday的值是3。 未赋值的是按照已赋值的顺序递增

enum Direction {
  Up ,
  Down = 2,
  Left ,
  Right = 5,
}


//0,2,3,5

除了数字值,枚举成员还可以是字符串值,例如:

enum Color {
    Red = 'red',
    Green = 'green',
    Blue = 'blue'
}

这样,Color.Red的值就是字符串'red'。枚举返回的是后面的值

枚举还提供了一些常用的方法,例如EnumName[EnumName.Member]可以通过枚举成员的值获取其名称,EnumName.Member.toString()可以将枚举成员转换为字符串。