TS的学习
TS大部分知识点在于JS,所以只记录一些TS特有的知识点
TS的中文网
| 官网 | 网址 |
|---|---|
| bootcss.com | TypeScript 中文手册 |
| tslang.cn | TypeScript中文网 |
| nodejs.cn | TypeScript 手册 |
降级编译
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)
字面量是在源代码中直接表示值的方式。这些值可以是数字、字符串、布尔值、对象、数组等。
- 数字字面量:
42,3.14 - 字符串字面量:
'Hello',"World" - 布尔字面量:
true,false - 对象字面量:
{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。
-
Object 类型:
Object是JavaScript中所有对象的基类。它不是基本类型(primitive type),而是引用类型(reference type)。- 使用
Object类型可以创建具有任意属性和方法的对象。 - 你可以通过点符号(
.)或方括号([])来访问或修改对象的属性。
-
基本类型(Primitive Types) :
- 基本类型包括:
Number、String、Boolean、Symbol、null、和undefined。 - 这些值是不可变的,并且是按值传递的。
- 基本类型包括:
-
内置类型(Built-in Types) :
- JavaScript中的所有数据类型,包括基本类型和引用类型,都可以被视为内置类型。
-
object(小写) :
object(小写)通常指的是JavaScript中任意对象类型的通用类型标识符。在typeof运算符的上下文中,它会返回非基本类型(如数组、函数、日期对象等)的值作为"object"。但是,这并不意味着所有的对象都是Object类型的实例。例如,数组不是Object的直接实例,但它们是继承自Object.prototype的。
-
访问对象的属性:
-
你可以使用点符号(
.)或方括号([])来访问或修改对象的属性。例如:javascript复制代码 let obj = { name: 'Alice', age: 30 }; console.log(obj.name); // 输出 "Alice" console.log(obj['age']); // 输出 30
-
总结:
- 使用
Object类型(注意大写)可以创建和操作具有属性和方法的对象。 - 使用
object(小写)通常是在typeof运算符的上下文中,用来表示一个非原始值。但是,这并不表示一个具体的类型,只是一个通用的分类。
object类型
TS (TypeScript) 中的对象类型有以下几种:
- object:表示任意对象类型,可以包含任意属性和方法。
let obj: object = {
name: 'John',
age: 25
};
- any:表示任意类型,可以赋值给任何类型的变量。
let anyObj: any = {
name: 'John',
age: 25
};
- 声明对象的属性和方法:
let person: {
name: string;
age: number;
sayHello: () => void;
} = {
name: 'John',
age: 25,
sayHello: () => {
console.log('Hello!');
}
};
- 接口:定义对象的形状,指定属性和方法的类型。
interface Person {
name: string;
age: number;
sayHello: () => void;
}
let person: Person = {
name: 'John',
age: 25,
sayHello: () => {
console.log('Hello!');
}
};
- 类:用类来创建对象,并定义类的属性和方法。
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 的区别如下:
-
Number vs number:
- Number 是 Number 对象的包装类,它包含了一些用于处理数字的方法和属性。在 TypeScript 中使用 Number 会得到一个对象。
- number 是 TypeScript 中的关键字,用于表示数字类型。
-
String vs string:
- String 是 String 对象的包装类,它包含了一些用于处理字符串的方法和属性。在 TypeScript 中使用 String 会得到一个对象。
- string 是 TypeScript 中的关键字,用于表示字符串类型。
-
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;
默认情况下null和undefined是所有类型的子类型。 就是说你可以把 null和undefined赋值给number类型的变量。
然而,当你指定了--strictNullChecks标记,null和undefined只能赋值给void和它们各自。 这能避免 很多常见的问题。 也许在某处你想传入一个 string或null或undefined,你可以使用联合类型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函数抛出错误后会终止程序的执行,因此它的返回类型是never。infiniteLoop函数会无限循环,永远不会结束,因此它的返回类型也是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=[]//这也是可以的
声明数组
- 声明一个数组变量并初始化:
let arr: number[] = [1, 2, 3, 4, 5];
- 使用
Array关键字声明一个数组变量并初始化:
let arr: Array<number> = [1, 2, 3, 4, 5];
- 使用
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];
以上是定义和初始化数组的方式,接下来可以使用下标访问数组元素,或使用数组的push、pop、slice等方法对数组进行操作。
元组
元组是 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()可以将枚举成员转换为字符串。