1.node,npm,yarn是什么?
node:js运行的环境,js运行的环境是V8引擎,node也内置V8引擎
npm:是包(依赖)的管理器,可以控制版本
yarn:也是包(依赖)的管理器,可以控制版本
2.TypeScript的安装
(1)全局安装,当前电脑任意位置都可以使用
npm install -global typescript
简写( npm i -g typescript)
npm:包的管理器
install:安装 ,简写为 i
global: 全局 -g
(2)局部安装,当前项目中安装
初始化项目 npm init -y(英文目录) npm init(中文目录)
npm install typescript
3.手动编译ts文件
(1)tsc 文件名 编译成js文件
(2)node 文件名
4.自动编译ts文件
(1) 安装 npm i ts-node-dev
(2) 在package.json中的scripts添加脚本
"scripts": {
"start": "ts-node-dev --respawn --transpile-only index.ts"
},
(3)通过npm start运行
5.Number类型
// 十进制
let a: number = 10;
// 二进制
let b: number = 0b1010;
// 八进制
let c: number = 0o744;
// 十六进制
let d: number = 0xf00d;
console.log(a);
console.log(b);
console.log(c);
console.log(d);
6.拿到项目进入项目中,npm install 安装依赖
7.类的创建
class Car {
// 字段[属性、成员变量]
brand: string;
timestamp: Date;
// constructor 初始化参数
constructor(brand: string, timestamp: Date) {
this.brand = brand;
this.timestamp = timestamp;
}
// 普通函数
disp(a: number): void {
console.log(`品牌:${this.brand}-----${a}`);
}
// 箭头函数
buy = (name?: string): string => {
console.log(this.brand);
return name;
};
}
8.类的使用
我们创建的类除了通过创建对象的方式去使用,还可以作为类型去使用
// 创建对象的方式一:
const car = new Car('法拉利', new Date());
console.log(car.brand, car.timestamp);
car.disp(10);
console.log(car.buy('张三'));
// 创建对象的方式二:
const baoma: Car = {
brand: '宝马',
timestamp: new Date(),
// 重写方法了
disp() {
console.log(`baoma is disp`);
},
buy(): string {
return '';
},
};
baoma.disp(10);
const foo = (car: Car) => {
console.log(car);
car.disp(10);
};
const bar = (a: number) => {
console.log(a);
};
foo(new Car('大众', new Date()));
9.static的使用
// 被static修饰的方法和属性,叫做静态方法和静态属性
// 静态方法和静态属性在使用的时候需要被类直接调用,不需要实例化(创建对象)
class Person {
static title:string | number = 10;
static sayHi(): void {
console.log(this.title);
}
}
console.log(Person.title);
Person.sayHi();
10.extends
TypeScript 支持继承类,即我们可以在创建类的时候继承一个已存在的类,这个已存在的类称为父类【基类】,继承它的类称为子类【派生类】
类继承使用关键字 extends,子类除了不能继承父类的私有成员(方法和属性)和构造函数,其他的都可以继承
TypeScript 一次只能继承一个类,不支持继承多个类,但 TypeScript 支持多重继承(A 继承 B,C继承 B)
子类可以重写父类的方法和属性,还可以拥有自己的方法和属性
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
sayHi = (): void => {
console.log(`${this.name} :我今年${this.age}`);
};
}
class Student extends Person {
constructor(name: string, age: number) {
super(name, age);
}
sayHi = (): void => {
console.log(`${this.name} :我今年${this.age},hi`);
};
speak = (): void => {
console.log(`speak`);
};
}
// class Children extends Student {
// constructor(name: string, age: number) {
// super(name, age);
// }
// }
const stu = new Student('张三', 18);
stu.sayHi();
stu.speak();
11.抽象类的概念和特点
被abstract修饰的类叫做抽象类,也叫做基类,证明只能作为父类使用
被abstract修饰的方法叫做抽象方法,被abstract修饰的属性叫做抽象属性,抽象类在被继承时,抽象方法和抽象属性必须重写
抽象类不能实例化,必须由子类(派生类)去创建实例
抽象方法不能由方法体
12.抽象类的定义
abstract class Animal {
abstract name: string;
abstract speak(): void;
abstract say: () => void;
}
// 抽象类在被继承的时候,必须重写抽象方法和属性
class Dog extends Animal {
name: string;
constructor(name: string) {
super();
this.name = name;
}
speak(): void {
console.log(`${this.name}:汪汪汪`);
}
say = () => void {};
}
const dog = new Dog('泰迪');
dog.speak();
13.接口
interface修饰
接口类似抽象类,但是在接口中定义的方法和属性都是不能有实值,属性没有具体值,方法没有方法体
接口不能实例化,只能被实现的子类(派生类)去实例化
子类可以同时实现多个接口,实现的关键字implements
// 定义接口
interface IPerson {
firstName: string;
lastName: string;
sayHi: () => void;
}
// 接口作为类型使用
const customer: IPerson = {
firstName: 'Tom',
lastName: 'Hanks',
sayHi: (): string => {
return 'Hi there';
},
};
// 定义接口
interface IA {
a: string;
}
// 类实现接口,同时实现多个接口
class Student implements IPerson, IA {
firstName: string;
lastName: string;
a: string;
constructor(firstName: string, lastName: string, a: string) {
this.firstName = firstName;
this.lastName = lastName;
this.a = a;
}
sayHi = (): void => {
console.log(this.firstName + this.lastName);
};
}
const stu = new Student('张', '三', '10');
stu.sayHi();
14.扩展接口
接口不能实现接口,但是可以扩展接口
interface IPerson {
firstName: string;
lastName: string;
}
// 接口可以被扩展
interface IB extends IPerson {
age: number;
}
class Student implements IB {
firstName: string;
lastName: string;
age: number;
}
15.泛型
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
// T 可以是任意字符 T K V
// 泛型:谁调用谁决定类型
function foo<T>(a: T): T {
console.log(a);
return a;
}
// 小刘
const p = new Person('张三', 18);
// 在调用的时候确定类型
foo<Person>(p);
// 老王
foo<Number>(10);
注意:由于Vscode的终端默认使用powershell,默认禁止输入脚本(指令)
以管理员身份运行 powershell
执行 set-ExecutionPolicy RemoteSigned;
输入y
ts/js中的模块化
情况一:统一导出,解构导入
// foo.ts 导出
const username = 'admin';
const sum = (a: number, b: number): number => {
return a + b;
};
// 统一导出模块
export { sum, username };
// main.ts 导入
import { username, sum } from './foo';
console.log(username);
console.log(sum(10, 20));
情况二:单独导出,解构导入
// foo.ts 单独导出
export const sayHello = (name: string): void => console.log(`${name}:hello`);
// main.ts
import { sayHello } from './foo';
sayHello('张三');
情况三:统一(单独)导出,作为一个对象导入
// main.ts
import * as foo from './foo';
console.log(foo.username);
foo.sayHello('王五');
情况四:默认导出(一个文件中只能有一个默认导出)
// foo.ts默认导出
export default function () {
console.log('默认导出函数');
}
// 也可以分开写
// function a() {
// console.log('默认导出函数');
// }
// // 默认导出
// export default a;
// main.ts 导入
import a from './foo';
a();
情况五:一起导入默认导出的和统一(单独)导出的
import a, { username, sum, sayHello } from './foo';
a();
console.log(username);
情况六:export和import结合使用
应用场景:比如工具类,在工具类文件夹下有很多的文件,别人在使用的时候必须知道所有文件的名称,但是这个就比较困难了,所以就可以在这个工具类文件夹下新建一个index文件,做统一导入导出,这样别人就只需要知道工具类文件夹就可以正常使用了
// formatDate.ts
/**
* 格式化时间
* @param date
* @returns 日期
*/
export const formatDate = (date: Date): string => {
return date.toLocaleDateString();
};
// formatString.ts
export const formatString = (a: any) => {
return a.toString();
};
// math.ts
export const random = Math.random();
// index.ts
export * from './formatDate';
export * from './formatString';
export * from './math';
// 在使用的地方进行导入
import { formatDate, formatString, random } from './src/09_模块化(2)/index';
console.log(formatDate(new Date()));
console.log(formatString(10));
console.log(random);