# TypeScript **Repository Path**: zhouAAA/type-script ## Basic Information - **Project Name**: TypeScript - **Description**: TS的学习入门 - **Primary Language**: TypeScript - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-01-20 - **Last Updated**: 2022-01-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # TypeScript ## 1.环境搭建 1. 在命令行上,运行 TypeScript 编译器: ```bash tsc helloworld.ts ``` 2. 在命令行上,通过 Node.js 运行这段代码: ```bash node helloworld.js ``` 3. vscode自动编译 ``` 1). 生成配置文件tsconfig.json tsc --init 2). 修改tsconfig.json配置 "outDir": "./js", "strict": false, 3). 启动监视任务: 终端 -> 运行任务 -> 监视tsconfig.json ``` ### webpack环境搭建 1. 初始化 - `tsc --init` - `npm init -y` 2. 下载依赖项 ` cnpm i -D typescript webpack webpack-cli ts-loader` 3. packjson包(依赖项) ```json "devDependencies": { "clean-webpack-plugin": "^4.0.0", "html-webpack-plugin": "^5.5.0", "ts-loader": "^9.2.6", "typescript": "^4.5.4", "webpack": "^5.66.0", "webpack-cli": "^4.9.1", "webpack-dev-server": "^4.7.3" } ``` 4. 添加`webpack.config.js` 文件 ```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/ }] } } ``` 5. 配置 `tsconfig.json` ```json { "compilerOptions": { "module": "es6",//模块化 "target": "es6",//打包成版本 "strict": true } } ``` 6. 修改`package.json` - 加上 `build` ```json "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "webpack" }, ``` 7. 即可使用 `npm run build` 打包 .ts 文件 ### webpack相关插件 1. 自动生成html文件 1. 依赖 `cnpm i -D html-webpack-plugin` 2. 使用 ```js // 引入自动生成html插件 const HTMLWebpackPlugin = require('html-webpack-plugin') // 配置webpack插件 plugins: [ //使用html模板 new HTMLWebpackPlugin({ template: "./public/index.html" //模板路径 }), ] ``` 2. 使用 `webpack`内置服务器 1. 依赖`cnpm i -D webpack-dev-server` 2. **配置启动方式** 1. 在 `package.json` 配置启动项 ```json "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "webpack", //使用chrome打开 "start": "webpack serve --open chrome.exe" }, ``` 3. 启动 `npm start`, 支持热更新. 3. 每次`build`时删除已经存在的 dist/目录 1. 依赖 `cnpm i -D clean-webpack-plugin` 2. 使用 ```js //引入清楚dist目录插件 const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // 配置webpack插件 plugins: [ new CleanWebpackPlugin(), new HTMLWebpackPlugin({ template: "./public/index.html" }), ] ``` 4. 设置引用模块(**模块化代码**) ```js // webpack.config.js resolve: { extensions: ['.ts', '.js'] } ``` ### Babel配置 1. 作用: 编译一些ES6的新语法 2. 安装: `cnpm i -D @babel/core @babel/preset-env babel-loader core-js` 3. 配置 ```js // 指定webpack打包时要使用的模块 module: { rules: [{ // test指定的是规则生效的文件 test: /\.ts$/, // 使用的loader use: [ //配置Babel { // 选择加载器 loader: 'babel-loader', // 设置预处理环境 options: { presets: [ [ //指定环境的插件 "@babel/preset-env", // 配置信息 { // 要兼容的目标浏览器及版本 targets: { "chrome": "58", "ie": "11" }, //指定corejs的版本 "corejs": "3", //使用corejs的方式 "usage" 表示按需加载 "useBuiltIns": "usage" } ] ] } }, 'ts-loader' ], exclude: /node_modules/ }] }, ``` ### CSS配置 1. 依赖项 `cnpm i -D less less-loader css-loader style-loader` 1. less: less核心 2. less-loader: less加载器 3. css-loader: css加载器 4. style-loader: 引入样式 2. webpack配置 ```js // 指定webpack打包时要使用的模块 module: { rules: [ // 配置Babel { // test指定的是规则生效的文件 test: /\.ts$/, // 使用的loader use: [ //配置Babel { // 选择加载器 loader: 'babel-loader', // 设置预处理环境 options: { presets: [ [ //指定环境的插件 "@babel/preset-env", // 配置信息 { // 要兼容的目标浏览器及版本 targets: { "chrome": "58", "ie": "11" }, //指定corejs的版本 "corejs": "3", //使用corejs的方式 "usage" 表示按需加载 "useBuiltIns": "usage" } ] ] } }, 'ts-loader', ], exclude: /node_modules/ }, // 设置less文件处理 { test: /\.less$/, use: [ "style-loader", "css-loader", "less-loader" ] } ] }, ``` ## build/webpack.config.js 1. 依赖环境 ```json "devDependencies": { "@babel/core": "^7.16.7", "@babel/preset-env": "^7.16.8", "babel-loader": "^8.2.3", "clean-webpack-plugin": "^4.0.0", "core-js": "^3.20.3", "html-webpack-plugin": "^5.5.0", "ts-loader": "^9.2.6", "typescript": "^4.5.4", "webpack": "^5.66.0", "webpack-cli": "^4.9.1", "webpack-dev-server": "^4.7.3" } ``` 2. webpack配置 ```js const path = require('path'); // 引入自动生成html插件 const HTMLWebpackPlugin = require('html-webpack-plugin') //引入清楚dist目录插件 const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // webpack配置项都要写在这 module.exports = { mode: 'development', // 指定入口文件 entry: "./src/index.ts", // 指定打包文件所在目录 output: { // 打包后文件的目录 path: path.resolve(__dirname, 'dist'), // 打包后文件的名称 filename: "bundle.js" }, // 指定webpack打包时要使用的模块 module: { rules: [{ // test指定的是规则生效的文件 test: /\.ts$/, // 使用的loader use: [ //配置Babel { // 选择加载器 loader: 'babel-loader', // 设置预处理环境 options: { presets: [ [ //指定环境的插件 "@babel/preset-env", // 配置信息 { // 要兼容的目标浏览器及版本 targets: { "chrome": "58", "ie": "11" }, //指定corejs的版本 "corejs": "3", //使用corejs的方式 "usage" 表示按需加载 "useBuiltIns": "usage" } ] ] } }, 'ts-loader' ], exclude: /node_modules/ }] }, // 配置webpack插件 plugins: [ new CleanWebpackPlugin(), new HTMLWebpackPlugin({ template: "./public/index.html" }), ], // 用来设置引用模块 resolve: { extensions: ['.ts', '.js'] } } ``` 1. 配置打包命令 ```json "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "webpack", "start": "webpack serve --open chrome.exe" }, ``` 2. 运行和打包 ```shell npm run start npm run build ``` ## 2. TS编译选项 ### 1. 编译单个TS文件 1. 直接编译 `tsc 文件.ts` 2. 监视编译 `tsc 文件.ts -w` ### 2. 同时编译多个TS文件 1. 需要配置 `tsconfig.json` ```json { // 用来指定那些TS文件需要编译 "include": [ "./src/**/*", //编译src目录下所有目录下的所有文件 ], // 不需要被编译的目录,有默认值 "exclude": [ "./src/test/**/*" ], // 编译器的选项 "compilerOptions": { // 编译为的ES版本 "target": "es2015", // 指定模块化的规范 commonjs "module": "es2015", // 指定项目中要使用的库, // "lib": [] // 用来指定编译后文件所在目录 "outDir": "./dist", //将代码合并为一个文件,so:不支持模块化 // "outFile": "", // 有错误时不编译 "noEmitOnError": true, // js开启严格模式 "alwaysStrict": true, // 严格检查模式 "strict": true } } ``` 2. 执行 `tsc -w` 命令, 编译所有ts文件,并监视 ## 3.TS常用语法 ### 1.TS类型 1. 基础类型 `let flag:boolean = true` `let num:number = 110` `let str:string = '周张恒'` ` let und: undefined = undefined` ` let nll: null = null` 2. any(任意类型) - 定义方式: `let any: any` - 不建议使用, 没意义 3. unknown(不确认类型) 1. 定义方式: `let unknown: unknown` 2. 可以接收任何类型, 但是不能给指定类型的变量赋值 ```typescript let unknown: unknown let S: string unknown = "zhou" // S = unknown 会报错不能直接赋值 S = unknown as string // 类型断言 S = unknown ``` 4. void (函数返回值) - 一般指定函数的返回值`function test():void{}` 5. *对象类型* 1. 基本定义 ```tsx let obj: {}; obj = {} obj = function () { } ``` 2. 进阶使用 ```tsx /* 可以用来指定对象中拥有那些属性 在属性名后面加上 ? 表示属性是可选的 */ let zhou: { name: string, age?: number } zhou = { name: '周张恒', age: 20 } // [propName: string]: any 表示任意类型的属性,可以接收多个属性 let ph: { name: string, [propName: string]: any } ph = { age: 18, name: "彭慧", sex: 'female' } ``` 6. 元组: 元组就是固定类型的数组 - 语法: [类型, 类型, 类型], **长度是被定义死的** ```tsx let h: [string, number, boolean] h = ['aaa', 123, false] ``` 7. 条件 `& |` ```typescript let f: number | string let ff: { age: number } & { name: string } ``` 8. 类型的别名`type` ```tsx type mytype = 1 | 2 | 3 let ab: mytype let ac: mytype ``` ## 4.面向对象 ### 1. 类 1. 类主要包含两个部分: **属性 and 实例** 2. 使用 `class`关键字来定义一个类 ```js class Person { } ``` ### 2. 属性 1. 属性分为 **实例属性** , **类属性** - 实例属性 - 需要实例化后通过 **实例对象.** 的形式访问 `zhou.name` - 类属性(静态属性) - 不需要实例化直接通过 **类.** 访问 `Person.age` ```typescript class Person { // 定义实例属性, 需要实例化后通过 实例对象. 的形式访问 name: string = '周张恒' // 只读属性,不可修改值 readonly name2: string = "彭慧" // 静态属性, 不要实例化直接通过 类. 访问 static age: number = 19 } const zhou = new Person(); console.log(zhou.name); console.log(Person.age); ``` 2. 方法 分为 实例方法, 静态方法 1. 实例方法 - 需要实例化后调用 2. 静态方法(static) - 直接使用类调用 ```typescript class Person { sayName(name: string): void { console.log(name); } static sayHello() { console.log('hello'); } } zhou.sayName('周周周') //实例对象调用 Person.sayHello() //类调用 ``` ### 3.构造器函数`constructor()` 1. 当 `new`时, 就会调用此构造器函数 2. 构造器函数中 `this` 指向是 实例化对象 ```typescript class Dog { name: string age: number constructor(name: string, age: number) { this.name = name this.age = age } } const x = new Dog('cz', 9) const y = new Dog('ab', 19) console.log(x); //Dog {name: 'cz', age: 9} console.log(y); //Dog {name: 'ab', age: 19} ``` ### 4. 继承和重写 1. TypeScript以整个文件夹都是相同作用域, 所以用立即执行函数作为闭包. 2. 子类继承父类中的属性和方法 ` class Dog extends Animal` 3. 重写: 与父类中方法同名时,可重写此方法 ```typescript (() => { class Animal { name: string age: number constructor(name: string, age: number) { this.name = name this.age = age } say() { console.log("我是动物"); } } // extends 继承父类中的方法 class Dog extends Animal { //与父类中方法同名时,可重写此方法 say(): void { console.log("汪汪汪"); } } class Cat extends Animal { say(): void { console.log('喵喵喵'); } } })() ``` ### 5.`super`关键字 1. `super`相当于父类,但只可以调用方法 2. 在子类的`constructor()`中必须包含 `super()`来实例化父类中的属性 ```typescript (() => { class Animal { name: string age: number constructor(name: string, age: number) { this.name = name this.age = age } say() { console.log("我是动物"); } } class Dog extends Animal { sex: number constructor(name: string, age: number, sex: number) { super(name, age) this.sex = sex } say(): void { super.say() //调用父类中的方法 } } const dog = new Dog('cz', 29, 0) console.log(dog); //Dog {name: 'cz', age: 29, sex: 0} dog.say() //我是动物 })() ``` ### 6.`abstract` 抽象类 1. **使用该属性定义的类不能进行实例化** 2. 使用该属性定义的方法,在子类中**必须重写** ```typescript (() => { abstract class Animal { name: string age: number constructor(name: string, age: number) { this.name = name this.age = age } // 抽象方法只能定义在抽象类中,子类必须对方法进行重写 abstract say(): void; } class Dog extends Animal { sex: number constructor(name: string, age: number, sex: number) { super(name, age) this.sex = sex } say(): void { console.log('哈哈哈哈'); } } })() ``` ### 7. 接口`interface` - 概念 - 接口就是定义相关规范, 仅此而已. - *接口中所有的属性都不能有实际的值* - *接口只定义对象的结构, 而不考虑实际值* - *在接口中所有的方法都是抽象的* - 定义接口 ```tsx interface myInter { name: string sayHello(): void; } ``` - 实现接口 - *定义类时,可以**使用类去实现一个接口*** - *实现接口就是使类满足接口的要求* ```tsx class inter implements myInter{ name: string = 'abc'; sayHello(): void { console.log('hello'); } } ``` ### 8. 属性的封装 1. TS可以在属性前添加属性修饰符 - `public`: 修饰的属性可以在任意的位置访问(修改)默认值 - 任何位置都能够访问 - `private`: 私有属性只能在内部进行访问(修改) - 通过在类中添加方法使得私有属性可以被外部访问(get,set) - `protected`: 受保护的属性, 只能在当前类和当前类的子类中访问 - 多用于继承 ```typescript (() => { class Person { /** * TS可以在属性前添加属性修饰符 * public: 修饰的属性可以在任意的位置访问(修改)默认值 * private: 私有属性只能在内部进行访问(修改) * -通过在类中添加方法使得私有属性可以被外部访问(get,set) * protected: 受保护的属性, 只能在当前类和当前类的子类中访问 * -多用于继承当中 */ public name: string private age: number protected sex: number constructor(name: string, age: number, sex: number) { this.name = name this.age = age this.sex = sex } get getName(): string { return this.name } get getAge(): number { return this.age } set setAge(age: number) { if (age >= 0) this.age = age } } class Zhou extends Person { test() { console.log(this.sex); super.setAge = 100 } } const zzh = new Person('周张恒', 19, 1) const zz = new Zhou('周张恒', 19, 1) zz.test() // 1 console.log(zz); // Zhou {name: '周张恒', age: 100, sex: 1} // zzh.age; //私有属性不能访问 zzh.setAge = 888 console.log(zzh.getAge); })() ``` 2. 属性的封装是为了让属性通过`get set`读取和修改, 让代码更加安全. - `get set`定义的方法中参数使用的是直接赋值法 `zzh.setAge = 888` 3. 类定义的语法糖 - 语法糖中的 `public` 不可省略. ```typescript class Test { //直接将属性定义到构造器中, 可以减去写 this constructor(public name: string) { } } const test = new Test("test") console.log(test); //Test {name: 'test'} ``` ### 9. 泛型 1. 在不知道属性类型的情况下可以使用泛型, 泛型会自动判断数据类型 2. 基础使用 ```tsx function f1(name: S): S { return name } f1('asas') // 可以指定多个泛型 function f2(name: S, age: N): N { return age } ``` 3. 对类使用泛型 ```typescript class Test{ constructor(public name: S) { } } const T = new Test('zzh') ``` 4. 指定接口类型泛型 `` ```typescript interface Inter { length: number } class Arr implements Inter { constructor(public length: number) { } } const arr = new Arr(100) /** * 表示I必须是Inter实现类(子类) * @param name * @returns */ function f3(name: I): number { console.log(name.length); return name.length } f3(arr) ```