1. TypeScript开发环境搭建
1. 下载Node.js(官网LTS是稳定版本,Current是最新版,我们建议使用稳定版)
64位:https://nodejs.org/dist/v16.17.0/node-v16.17.0-x64.msi
2. 安装Node.js(安装位置自己决定,能找到就行,一直无脑点下一步到安装即可)
3. 使用npm全局安装typescript
npm i -g typescript
4. 创建一个ts文件
5. 使用tsc对文件进行编译
2. ts类型
let a: number;
a = 10;
a = 33;
// 这里报错, 只能使用number类型
// a = 'hello';
let b: string;
b = '123';
let c: boolean = false;
注意:如果在ts直接let c = false; ts默认判断c的类型是boolean
// 函数的返回值类型是number(result)
function sum(a: number, b: number): number {
return a + b;
}
let result = sum(123, 456);
// 联合类型, | 或
let b: boolean | string;
b = true;
b = 'hello';
// 显式any 任意类型
let d: any; // 隐式any let d;
d = 10;
d = '123';
d = false;
// unknown未知类型
let e: unknown;
e = 10;
e = true;
e = '123';
let s: string;
// 类型断言, 可以用来告诉解析器变量的实际类型
s = e as string;
// void 表示没有返回值的函数
function fn(): void {
// return undefined; 可以
}
// never 表示永远不会返回结果
function fn(): never {
// return undefined; 不可以
}
// object a表示一个js对象
let a: object;
a = {};
a = function () {};
// ?表示有age和没有age都可以
let b: {name: string, age?: number};
// let b: {name: string, [propName: string]: any}; 就可以随便写对象属性
b = {name: '123'};
let d: (a: number, b: number) => number;
d = function (n1, n2) {
return n1 + n2;
}
let g: Array<number>;// let g = number[]; let g = string[];
// 元组, 元组就是固定长度的数组
let h: [string, string];
h = ['1', '2'];
// 定义一个枚举
Enum Gender {
Male,
Female
}
// enum 枚举
let i: {name:string, gender: Gender};
i = {
name: 'a孙悟空',
gender: Gender.Male // ,
};
type myType = 1 | 2 | 3;
let a: myType;
let b: myType;
a = 1;
b = 1;
3. ts编译选项
// 监听vscode文件内容改变就自动编译
tsc index.ts -w
// 在文件夹下创建tsconfig.json, 在终端输入tsc, 则该文件夹下所有ts都会被编译
// 同理,使用tsc -w 则可以监听该文件夹下所有ts文件内容的变化
// tsconfig.json是ts编译器的配置文件,ts编译器可以根据它的信息来对代码进行编译
// include用来指定哪些ts文件需要被编译
// ./src/**/* 一个*表示任意文件 两个*表示任意目录
// exclude表示不包含, 不需要被编译的文件目录
// 默认值["node_modules", "bower_components", "jspm_packages"]
// extends 定义被继承的配置文件(很少用到)
// files 指定被编译文件的列表, 只有需要编译的文件少时才会用到(很少用到)
// compilerOptions 编译选项是配置文件中非常重要也
// 在part文件夹下创建tsconfig.json, 以及src文件夹,src文件夹下创建app.ts, 此时在part
对应的终端使用tsc,则src下的ts文件会自动编译生成js文件(注意:根目录ts是不会编译的)
{
"include": [
"./src/**/*"
],
"exclude": [
"./src/hello/**/*"
],
// "extends": "./config/base",
// "files": [
// "core.ts",
// "sys.ts"
// ],
"compilerOptions": { // 编译器的选项
// target 用来指定ts被编译为的ES的版本(ESNext表示ES最新的版本)
// es3 es5 es6(es2015) es2016 es2017...
"target": "ES6",
// 模块,指定要使用的模块化的规范,commonjs或者es2015...等等
"module": "es2015",
// lib用来指定项目中要用的库,一般都不要改或动
// "dom" , 用来在ts文件输入d时可以直接显示document
"lib": [],
// outDir 用来指定编译后文件所在目录(ts生成的js文件都放在dist文件夹下)
"outDir": "./dist",
// outFile 将代码合并成一个文件, 设置后所有的全局作用域中的代码都会合并到同一个文件中
// 使用这个后,需要将module改成module: "system"就不会报错了
// "outFile": "./dist/app.js",
// allowJs 是否对js文件进行编译 默认false 与checkJs搭配使用
"allowJs": false,
// checkJs 是否检查js代码是否语法规范,默认false
"checkJs": false,
// 是否移除注释,默认false
removeComments: false,
// 不生成编译后的文件,默认false
"noEmit": false,
// 当有错误时不生成编译后的文件,默认false
noEmitOnError: false,
// alwaysStrict 用来设置编译后的文件是否使用严格模式,默认false
alwaysStrict: false,
// noImplicitAny true表示不允许隐式any类型
noImplicitAny: false,
// true时,function f2() {alert(this)}报错,因为this指向谁不确定
"noImplicitThis": false,
// 严格的检查空值
"strictNullChecks": false,
// 一般写在前面,所有严格检查总开关,如果开起来就把所有严格选项全部都开起来了
"strict": false
}
}
4. 使用webpack打包ts代码
1. 第一步
// 创建文件夹part, 在终端输入: npm init -y , 这个是为了在此文件夹下生成package.json, 用来管理我们的项目。
npm init -y
2. 第二步
// 安装webpack需要的依赖
// D表示开发依赖
npm i -D webpack webpack-cli typescript ts-loader
// 写webpack的配置文件,webpack.config.js
代码如下:
// 引入一个包
const path = require('path');
// webpack中的所有配置信息都应该写在module.exports中
module.exports = {
// 指定入口文件
entry: "./src/index.ts",
// 指定打包文件所在目录
output: {
// 指定打包的目录
path: path.resolve(__dirname, 'dist'),
// 打包后的文件
filename: "bundle.js"
},
// 指定webpack打包时要使用模块
module: {
// 指定要加载的规则
rules: [
{
// test指定的是规则生效的文件
test: /\.ts$/,
// 要使用的loader
use: 'ts-loader',
// 要排除的文件
exclude: /node_modules/
}
]
}
};
3. 第三步
// 创建tsconfig.json
{
"compilerOptions": {
"module": "ES2015",
"target": "ES2015",
"strict": true
}
}
4. 第四步
在package.json中scripts加:build
"script": {
"build": "webpack --mode development" // "build": "webpack"
}
5. 第五步,在ts文件内写代码,然后执行npm run build
function sum (a: number, b: number): number {
return a + b;
}
console.log(sum(123, 456));
----------------------------------------------------------------------------------------
1. 第一个
// 此时已经差不多了,接下来继续完善, 此依赖可以在dist文件夹生成html文件而不需要自己创建
npm i -D html-webpack-plugin
// 然后在第二部的代码内添加对应代码
代码如下:
// 引入一个包
const path = require('path');
const HTMLWebpackPlugin = require('html-webpack-plugin');
// webpack中的所有配置信息都应该写在module.exports中
module.exports = {
// 指定入口文件
entry: "./src/index.ts",
// 指定打包文件所在目录
output: {
// 指定打包的目录
path: path.resolve(__dirname, 'dist'),
// 打包后的文件
filename: "bundle.js"
},
// 指定webpack打包时要使用模块
module: {
// 指定要加载的规则
rules: [
{
// test指定的是规则生效的文件
test: /\.ts$/,
// 要使用的loader
use: 'ts-loader',
// 要排除的文件
exclude: /node_modules/
}
]
},
// 配置webpack插件
plugins: [
new HTMLWebpackPlugin({
// title: "这是一个自定义的title"
template: "./src/index.html"
})
]
};
2. 第二个
// 让这个项目可以直接在这个服务器中运行, 直接打开浏览器界面
npm i -D webpack-dev-server
// 在package.json的scripts添加start, 然后npm start就可以启动项目并实时监听文件变化了
"script": {
"build": "webpack --mode development", // "build": "webpack"
"start": "webpack serve --open --mode development" // 后面mode不写vscode会报错
}
3. 第三个
npm i -D clean-webpack-plugin
// 然后在第二部的代码内添加对应代码
代码如下:
// 引入一个包
const path = require('path');
// 引入html插件
const HTMLWebpackPlugin = require('html-webpack-plugin');
// 引入clean插件
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
// webpack中的所有配置信息都应该写在module.exports中
module.exports = {
// 指定入口文件
entry: "./src/index.ts",
// 指定打包文件所在目录
output: {
// 指定打包的目录
path: path.resolve(__dirname, 'dist'),
// 打包后的文件
filename: "bundle.js"
},
// 指定webpack打包时要使用模块
module: {
// 指定要加载的规则
rules: [
{
// test指定的是规则生效的文件
test: /\.ts$/,
// 要使用的loader
use: 'ts-loader',
// 要排除的文件
exclude: /node_modules/
}
]
},
// 配置webpack插件
plugins: [
new CleanWebpackPlugin(),
new HTMLWebpackPlugin({
// title: "这是一个自定义的title"
template: "./src/index.html"
})
],
// 用来设置引用模块, 告诉它凡是以js,ts结尾都是可以使用模块化
resolve: {
extensions: ['.ts', '.js']
}
};
4. 安装babel,处理兼容性问题
npm i -D @babel/core @babel/preset-env babel-loader core-js
// 创建tsconfig.json
// 然后在第二部的代码内添加对应代码
代码如下:
// 引入一个包
const path = require('path');
// 引入html插件
const HTMLWebpackPlugin = require('html-webpack-plugin');
// 引入clean插件
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
// webpack中的所有配置信息都应该写在module.exports中
module.exports = {
// 指定入口文件
entry: "./src/index.ts",
// 指定打包文件所在目录
output: {
// 指定打包的目录
path: path.resolve(__dirname, 'dist'),
// 打包后的文件
filename: "bundle.js",
// 告诉webpack不使用箭头函数
environment: {
arrowFunction: false
}
},
// 指定webpack打包时要使用模块
module: {
// 指定要加载的规则
rules: [
{
// test指定的是规则生效的文件
test: /\.ts$/,
// 要使用的loader
use: [
// 配置babel
{
// 指定加载器
loader: "babel-loader",
// 设置babel
options: {
// 设置预定义的环境
presets: [
[
// 指定环境的插件
"@babel/preset-env",
// 配置信息
{
// 要兼容的目标浏览器
targets: {
"chrome": "88"
},
// 指定corejs版本
"corejs": "3",
// 使用codejs的方式:usage表示按需加载
"useBuiltIns": "usage"
}
]
]
}
},
'ts-loader' // 后面的先执行
],
// 要排除的文件
exclude: /node_modules/
}
]
},
// 配置webpack插件
plugins: [
new CleanWebpackPlugin(),
new HTMLWebpackPlugin({
// title: "这是一个自定义的title"
template: "./src/index.html"
})
],
// 用来设置引用模块, 告诉它凡是以js,ts结尾都是可以使用模块化
resolve: {
extensions: ['.ts', '.js']
}
};
5. ts-类的定义
// 创建part文件夹,part下再创建src文件夹以及tsconfig.json
// tscondig.json代码如下:
{
"compilerOptions": {
"module": "es2015",
"target": "es2015",
"strict": true,
"outDir": "./dist", // 输出,往dist添加
"noEmitOnError": false // ts编译有错误时无法通过
},
"include": [
"./src/**/*"
]
}
// 以abstract开头的类是抽象类
// 抽象类和其他类区别不大,只是不能用来创建对象
// 抽象类就是专门用来被继承的类
抽象类abstract
abstract class Animal {
name: string;
constructor (name: string) {
this.name = name;
}
// 定义一个抽象方法
// 抽象方法使用abstract开头,没有方法体
// 抽象方法只能定义在抽象类中,子类必须对抽象方法进行重写
abstract sayHello ():void;
}
class Cat extends Animal {
// 不写sayHello就直接报错
sayHello () {
console.log('哈哈哈');
}
}
// 接口
// 接口用来定义一个类结构, 用来定义一个类中应该包含哪些属性和方法
// 同时接口也可以当成类型声明去使用
// 写了2个inteface不会报错,会统一成一个inteface,类型内有三个参数
// 接口中的所有属性都不能有实际的值,只定义对象的结构而不考虑实际值
interface myInterface {
name: string;
age: number;
}
interface myInterface {
gender: string;
sayHello(): void; // 接口中的所有属性都不能有实际的值,只定义对象的结构而不考虑实际值
}
const obj: myInterface = {
name: '',
age: 1,
gender: '男'
}
// 定义类时,可以使用类去实现一个接口
// 实现接口就是使类满足接口的要求
class MyClass implements myInterface {
name: string;
constuctor (name: string) {
this.name = name;
}
sayHello () {
console.log('hello');
}
}
// 属性的封装
// public 修饰的属性可以在任意位置访问(修改)默认值
// private 私有属性,只能在类内部进行访问(修改)默认值
// protected // 受保护的属性,只能在当前类和当前类子类中使用, 用obj.属性是无法访问的
class Person {
private name: string;
private age: number;
constructor (name: string, age: number) {
this.name = name;
this.age = age;
}
// 定义方法,用来获取name属性
getName () {
return this.name;
}
setName (value: string) {
this.name = value;
}
}
const per = new Person('孙悟空', 18);
per.setName('猪八戒');
// console.log(per.name); // 报错,私有属性无法访问
console.log(per.getName());
// ts设置getter方法
class Person {
name: string;
constuctor (name: string) {
this.name = name;
}
get name () {
return this.name;
}
set name (value: string) {
this.name = value;
}
}
const per = new Person('孙悟空', 18);
per.name= 20;// setter方法
// 泛型
// 定义函数或者类时,如果遇到类型不明确就可以使用泛型,泛型就是不确定的类型
function fn<T> (a: T): T {
return a; // T就是泛型
}
// 可以直接调用具有泛型的函数
const res1 = fn(10); // 不指定泛型,TS可以自动对类型进行判断
console.log(res1);
const res2 = fn<string>('hello'); // 指定泛型
console.log(res2);
function fn2<T, K> (a: T, b: K):T {
return a;
}
const res3 = fn2<number, string>(123, 'hello');
console.log(res3);
interface Inter {
length: number;
}
// T extends Inter表示泛型T必须是Inter实现类(子类)
function fn3<T extends Inter>(a: T): number {
return a.length;
}
const res4 = fn3('123');
console.log(res4);
class MyClass<T> {
name: T;
constructor (name: T) {
this.name = name;
}
}
const mc = new MyClass<string>('孙悟空');
console.log(mc);