一、安装
npm -g install ts-node typescript
二、定义变量
1、number类型
// 先定义 后给值
let a: number;
a = 10;
// 定义类型 直接给值
let a: number = 10;
// 声明不给类型直接给值, 给什么值就是什么类型
let a = 10
2、boolean类型
let a: boolean = false
3、声明不给类型直接给值 给什么值就是什么类型
let a = false; // 类型为boolean
4、使用字面量进行类型声明
let a: 10;
a = 10;
a = 11; // 报错
//联合类型
let b: 1 | 2;
b = 1;
b = 2;
b = 3; // 报错 b的值只能是1和2
// c的类型可以是boolean、string两种类型
let c: boolean | string;
5.、any任意类型
let d: any; // 显示声明any类型
d = 10;
d = 'hello';
d = true;
let a; // 隐式any
6、unknown表示未知类型的值
let e: unknown;
e = 10;
e = 'hello';
e = true;
let d: any;
s = d; // d是类型是any,它可以赋值给任意类型
未知类型不可以给已知的类型变量赋值
let e: unknown;
let s: string;
s = e; // 报错e的类型是未知类型 而s是字符串类型
// 解决办法
方法一:if判断一下
if(typeof e === 'string'){
s = e
}
方法二:类型断言(用来告诉解析器变量的实际类型)
s = e as string
//或
s =<string>e;
7、void用来表示空(用函数为例 , 表示没有返回值)
function fn(): void {
return 或 return undefine 或 returnfine
}
8、never 表示永远不会有返回结果
function fn2(): never {
throw new Error('报错了')
}
9、object
let a: object;
a = {}
a = function() {}
10、在属性名后上加?表示可选
let b: { name: string, age?: number }
b = { name: '郑建', age: 18}
b = { name: '郑建'}
11、[propName: string]: any(表示任意类型的属性)
let c: {name: string, [propName: string]: any};
c = { name: '郑建', age: 18, gender: '男' }
12.数组声明
// 类型[]
// Array<类型>
// string[]表示数组里面的元素都是string类型
let e: string[];
e = ['a', 'b', 'c']
// Array<number> 表示数组里面的元素都是数字
let g: Array<number>;
g = [1, 2, 3]
13、元组类型 (就是不可变的数组)
let h: [string, string];
h = ['hello', 'a']
14、enum枚举
enum Gender {
male = 0,
female = 1,
}
let i: { name: string, gender: Gender }
i = {
name: '郑建',
gender: Gender.male
}
console.log(i.gender === Gender.male);
15、类型别名
type myType = 1 | 2 | 3 | 4;
let k: myType;
k = 6; //报错 k的值只能是1 2 3 4
二、let 与 const
声明变量的时候,我们推荐是用let和const,而不推荐var,并加上类型说明,且作用域为块级即以{}为界。
let lang: string = 'hello world';//如果省略类型说明,TS也可进行自动推断
lang = 2022; //赋值错误! 如果需要可以使用联合类型:let lang: number | string = 'TS';
let age: number = 20;
const num: number = 6.66666;//num以后不可改变,只可以读取,类似常量
num = 3.14; //错误
三、解构
将对象、数组中的元素拆分到指定变量中,以方便使用。
//解构数组
let array = [1, 2, 3, 4];
let [one, two] = array; //注意使用[]
console.log(one); // 1
console.log(two); // 2
let [first, ...others] = array; //剩余变量。...others是一个可变长度的数组
console.log(...others); // 2 3 4
//...是一个展开运算符
let newArr = [0, ...others, 5];
console.log(newArr); // 0 1 2 3 4 5
//解构对象
let People = {
name: "xiaoyi",
age: 20,
sex: "male"
};
let {name, age} = People;//注意使用{},且变量名需与对象中道属性名一致
console.log(name, age); // xiaoyi 20
四、函数
1、需要使用完整函数类型定义。
//命名函数,有完整的参数和返回类型。可以不用,TS将自动进行类型推断但推荐使用!
function sum(x: number, y: number): number {
return x + y;
}
//匿名函数
let res_sum = function(x: number, y: number): number { return x + y; };
console.log(sum(1, '2')); //参数类型必须和形参的类型一致
console.log(sum(1)); //参数个数必须和函数的形参个数一致
console.log(typeof sum(1, 2)); //打印出函数的返回值类型
2、可选参数
//可选参数,必须放在必要参数后
function greeting(firstName: string, lastName?: string) {
if(lastName) { //判断lastname是否有值传进来
return `Hello ${firstName} ${lastName}!`; //使用模板字符串进行拼接
}
return `Hello ${firstName}!`;
}
console.log(greeting('周'));
console.log(greeting('周', '晓忆'));
console.log(greeting('周', '晓忆', '你好')); //参数个数 !== 函数的形参个数不一致,产生错误。
3、默认参数【有缺省值】
//默认参数,不必在必要参数后
function greeting(firstName: string, lastName = 'yinjie') {
return `Hello ${firstName} ${lastName}!`;
}
console.log(greeting('zhou'));
console.log(greeting('zhou', 'xiaoyi'));
console.log(greeting('zhou', 'xiaoyi', 'Yong'));//参数个数 !== 函数的形参个数不一样发生错误!
4、不定长参数
//剩余参数,会被当做个数不限的可选参数。可以一个都没有,也可以有任意个
function greeting(firstName: string, ...restName: string[]) {//...代表的是一个可变长度的数组
return `Hello ${firstName} ${restName.join(' ')}!`;
}
console.log(greeting('zhou', 'wang', 'li', 'liu', 'guan', 'zhang', 'qin'));
console.log(greeting('zhou'));
5、箭头函数
特点:简化函数定义、解决this问题。但是可读性比较差。
// 无参数,函数体代码只有一行,则该行结果即为函数返回值
let greeting1 = () => `Hello TS!`; // return可以省略
console.log(greeting1()); // Hello TS!
// 一个参数,函数体代码只有一行,则该行结果即为函数返回值
let greeting2 = (name: string) => `Hello ${name}`; // return可以省略
console.log(greeting2('QiGe')); // Hello QiGe
//两个及以上的参数,函数体代码只有一行,则该行结果即为函数返回值
let add1 = (n1: number, n2: number) => n1 + n2;
console.log(add1(1, 2)); // 3
//两个及以上的参数,函数体代码多于一行,则必须用{}包裹,且显式给出return
let add2 = (n1: number, n2: number) => {
let sum = n1 + n2;
return sum;//改为sum++结果如何?
}
console.log(add2(1, 2)); // 3
五、类class
类是属性和函数的集合,是生成对象(Object)或类实例的模板。
1、类的定义和使用
关键字get 定义方法: 这个方法用于只读属性的,不可修改属性
关键字set定义方法: 这个方法用于修改属性是
readonly定义属性: readonly使其只能在初始化时赋值,以后不可更改
// getter和setter
class People { // class是关键字,类名默认全部大写首字母
private readonly _name: string; // 私有属性,外部不可访问。readonly使其只能在初始化时赋值,以后不可更改。
private _sex: string; // 私有属性,习惯以_开头进行命名
constructor(name: string, sex: string){ // 构造函数,一般用于初始化
this._name = name;
this._sex = sex;
}
get name(): string {
return this._name;
}
set name(value: string) { // 错误! _name有readonly属性,不可以被修改
this._name = value;
}
get sex(): string {
return this._sex;
}
set weather(sex: string) {
this._sex = sex;
}
}
let people = new People('zhouxiaoyi', 'male'); // 使用new关键字生成对象
console.log(people.name, people.weather);
people.weather = 'sunny'; // OK
people.name = 'Wang'; // 只读属性,不可以被修改
console.log(people);
2、静态属性
类中的属性或函数有static修饰,则可直接使用而不需要实例化
// 静态属性,内建或自定义,无需new即可使用,可以直接通过类名进行访问
// Math是一个包装类,自带的,里面的所有方法都是静态的。
console.log(Math.round(89.64)); // 90
console.log(Math.pow(2, 8)); // 256
class Tool {
static title = 'box';
static printInfo() {
console.log('The box can contain pens!');
}
}
// 静态方法与静态函数可以直接通过类名直接访问。
console.log(Tool.title);
Tool.printInfo();
3、继承
面向对象有三大特性:封装、继承、多态。
可以通过extends关键字继承其它类,从而成为其子类。
class Animal {
// 当构造函数传入的参数加上了“访问权限控制符”,则同时会声明同名类属性,并赋值
constructor(public name: string) { }
protected log(message: string) {
console.log(message);
}
move(distanceInMeters: number = 0) {
this.log(`${this.name} moved ${distanceInMeters}m.`); // 请注意name来自何处
this.log('==============');
}
}
class Horse extends Animal {
constructor(name: string) {
// 这里创建了构造函数 必须要调用父亲的构造器 通过super
super(name); // 通过super调用父类构造器
}
run(distanceInMeters = 50) { // 自己独有的函数
this.log("Clop, clop...");
super.move(distanceInMeters); // 通过super调用父类方法
}
}
class Eagle extends Animal {
constructor(name: string) { super(name); }
reborn() { // 自己独有的函数
console.log('Reborn? It is a joke, hahaha!');
}
}
let tom: Horse = new Horse("Tommy the Palomino");
tom.run(8964);
let sam: Eagle = new Eagle("Sammy the Hawk");
sam.move(1024); // sam的move函数来自何处?
sam.reborn();
六、模块化、组件化、工程化
我们经常说的模块化开发、组件化开发、工程化开发但是有些人可能对这种词比较陌生,下面我来说说,
模块化:模块化, 首先先知道模块是什么? 模块就是一个js文件,那模块化就是我们写的东西都放在一个一个js文件里,比如说公共的js逻辑代码 我们写好放到一个js里, 我们哪个页面需要的话就引入这个模块,这就是我理解的模块化开发,实现代码的复用 降低代码冗余、提高开发效率和降低开发成本。
组件化: 一个页面可以分为很多很多的小组件,每个组件都有自己要实现的功能,而且有些组件可以多个页面的复用,需要就引入进来 ,这就是组件化开发
工程化:工程化就好比厂里的流水线,一套流程下来该有的东西都给你安装上,不需要不一个一个依赖的引入,这个创建项目的时候用到比如 用vite创建项目 或则webpack创建项目