TypeScript初步学习

为什么80%的码农都做不了架构师?>>>TypeScript初步学习
文章图片

一、安装使用
1??npm install typescript -g; // 安装typescript
2??初始化项目: 进入项目文件夹后:npm init -y 生成package.json文件;
3??tsc --init,创建tsconfig.json文件,这是ts项目的配置文件,可以设置ts的编译参数;
4??安装@types/node模块:主要用来解决模块声明问题;
5??创建编写ts后缀文件,VSCode-任务-运行生成任务-构建,将ts文件转换为js文件; // 或直接在cmd中运行 tsc ts文件名,来编译ts文件;
6??在vue中使用(先将webpack升级到4版本(如果不是报错参考:https://blog.csdn.net/qq_25243451/article/details/80331269)):
1、vue-cli创建项目之后:安装编译器 ts-loader: npm i ts-loader -D;
2、然后去webpack.base.conf.js文件中配置:

extensions: ['.js', '.vue', '.json', '.ts']


{ test: /\.ts$/, loader: 'ts-loader', options: { appendTsSuffixTo: [/\.vue$/], } },

3、修改tsconfig.json文件,一下列出我自己的配置(初学)
{ // "compileOnSave": true,// 可以让ide在保存文件时根据tsconfig.json重新生成文件 "compilerOptions": { /* Basic Options */ "target": "es5",/* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ "module": "esnext",/* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ // "lib": [],/* 编译过程中需要引入的库文件的列表. */ "allowJs": true,/* 允许编译js文件. */ // "checkJs": true,/* 在js文件中报告错误,需与allowJs配合使用. */ "jsx": "preserve",/* 在.tsx文件中支持JSX: 'preserve', 'react-native', or 'react'. */ // "declaration": true,/* 生成相应的 '.d.ts' 文件. */ // "declarationMap": true,/* Generates a sourcemap for each corresponding '.d.ts' file. */ "sourceMap": true,/* Generates corresponding '.map' file. */ "pretty": true, // "outFile": "./",/* 将输出文件合并为一个文件. */ // "outDir": "./",/* 重定向输出目录. */ // "rootDir": "./",/*仅用来控制输出目录结构 - - outDir. */ // "composite": true,/* Enable project compilation */ // "removeComments": true,/* Do not emit comments to output. */ // "noEmit": true,/* Do not emit outputs. */ // "importHelpers": true,/* Import emit helpers from 'tslib'. */ // "downlevelIteration": true,/* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ // "isolatedModules": true,/* Transpile each file as a separate module (similar to 'ts.transpileModule'). *//* Strict Type-Checking Options */ "strict": true,/* Enable all strict type-checking options. */ "noImplicitAny": true,/* 在表达式和声明上有隐含 'any' 类型时报错. */ // "strictNullChecks": true,/* 在严格的null检查模式下,null和undefined值不包含在任何类型里,只允许它们自己和any来赋值. */ "strictFunctionTypes": true,/* 禁用函数参数双向协变检查. */ // "strictPropertyInitialization": true,/* 确保类的非undefined属性已经在构造函数里初始化,与strictNullChecks同时使用. */ // "noImplicitThis": true,/* 当'this'表达式的值为any类型的时候生成一个错误. */ // "alwaysStrict": true,/* 以严格模式解析并为每个源文件生成 "use strict"语句. *//* Additional Checks */ // "noUnusedLocals": true,/* 若有未使用的局部变量则报错. */ // "noUnusedParameters": true,/* 若有未使用的参数则报错. */ // "noImplicitReturns": true,/* 不是函数的所有返回路径都有返回值时报错. */ // "noFallthroughCasesInSwitch": true,/* 报告switch语句的fallthrough错误(即,不允许switch的case语句贯穿). *//* Module Resolution Options */ "moduleResolution": "node",/* 'node' (Node.js) or 'classic'决定如何处理模块. */ // "baseUrl": "./",/* 解析非相对模块名的基准目录. */ // "paths": {},/* 模块名基于'baseUrl'的路径映射的列表. */ // "rootDirs": [],/* 根文件夹列表,表示运行时组合工程结构的内容. */ "typeRoots": [/* 要包含的类型声明文件路径列表. */ "node_modules/@types", "./types" ], "types": [/* 要包含的类型声明文件名列表. */ "node" ], "allowSyntheticDefaultImports": true,/* 允许从没有设置默认到处的模块中默认导入. */ "esModuleInterop": true/* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ // "preserveSymlinks": true,/* 不把符号链接解析为其真实路径;将符号链接文件视为真正的文件. *//* Source Map Options */ // "sourceRoot": "",/* 指定TypeScript源文件的路径,以便调试器定位。当TypeScript文件的位置是在运行时指定使用此标记,路径信息会被加到sourceMap里. */ // "mapRoot": "",/* 为调试器制定sourcemap文件的路径,而不是使用生成时的路径。当.map文件是在运行时制定的,并不同与js文件的地址时使用实这个标记,路径会被嵌入到sourceMap中. */ // "inlineSourceMap": true,/* 生成单个sourcemaps文件,而不是将每sourcemaps生成不同的文件. */ // "inlineSources": true,/* 将代码与sourcemaps生成到一个文件中,与 '--inlineSourceMap' or '--sourceMap' 同时使用. *//* Experimental Options */ // "experimentalDecorators": true,/* 启用实验性的es装饰器. */ // "emitDecoratorMetadata": true,/* 给源码里的装饰器声明买啥概念设计类型元数据. */ }, /* 如果"files"和"include"都没有被指定,编译器默认包含当前目录和子目录下所有的TypeScript文件(.ts, .d.ts 和 .tsx),排除在"exclude"里指定的文件 */ "files": [ // 需要编译的文件 "types/index.d.ts" ], "include" : [ // 包含的某个路径下的文件 "src/**/*", "src/*" ], "exclude": [ // 拒绝某些路径下的文件 "node_modules" ] }

4、修改main.js文件
【TypeScript初步学习】把项目主文件main.js修改成main.ts,里面的写法基本不变,但是有一点需要注意:
引入Vue文件的时候需要加上.vue后缀,否则编辑器识别不到;把webpack的entry文件也修改成main.ts
5、TypeScript并不支持Vue文件,所以需要告诉TypeScript*.vue文件交给vue编辑器来处理。在根目录创建一个types文件加然后在其下,创建index.d.ts文件,(也可以在src目录中创建,次文件需要到tsconfig.json>>files中引入编译) 文件内容为
declare module "*.vue" { import Vue from 'vue' export default Vue }

6、到此一般没什么问题,npm run dev 就可以运行。
7、到这一步告诉你一个消息。如果用vue-cli3.0版本,以上无需配置就能运行。
二、基础类型
let flag : boolean = false// 布尔 let age : number = 666 // 数字 // ts还支持二进制和八进制 let name : string = "二狗子" // 字符串 let attr = `小狗` let desc : string = `${name}是一只${attr}` let list : number[] = [1, 2, 3] // 数组 // 表示由此类型组成的数组 let list1 : Array = [1, 2, 3] // 泛型数组 // Null和Undefined let u : undefined = undefined let n : null = null/* Any */ /* 当在编程阶段还不知道定义什么类型的时候,就可以用Any类型,它可以让值直接通过编译阶段 */ // TypeScript友好的为我们提供了一种特殊的类型any,比如我们在程序中不断变化着类型,又不想让程序报错,这时候就可以使用any了 let notSure: any = 4; notSure = "string"; notSure = true; /* Void */ // 它不表示任何一个类型 function warnUser(): void { // 当一个函数没有返回值时 console.log("This is void message"); } // 声明一个void类型的变量只能为它赋予undefined和null let unusable: void = undefined; /* 元组Tuple */ /* 元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。 */ let x: [string, number]; x = ['hello', 10]; // OK x = [10, 'hello']; // Error/*枚举*/ enum Direction { // 默认情况下从0开始 // 此处Up值为1,Right为2 Up = 1, Right, Down, Left } let a: Direction = Direction.Right console.log(a) // 2 enum Direction1 { // Up值为0,Right为1 Up, Right, Down, Left } let b: Direction1 = Direction1.Up console.log(b) // 0/* Never */ /* never类型表示的是那些用不存在的值的类型;它可以赋值给任何类型,但是任何类型都不能赋值给never */ function error (message: string) : never { throw new Error(message) }

三、接口
// 接口 interface LabelledValue { // 它代表有个label属性且类型为string的对象 label: string } function printLabel (labelledObj: LabelledValue) { console.log(labelledObj.label) } let myObj = {size: 10, label: "Size 10 Object"} // 可以传入很多参数,但是必须包含一个label属性且类型为string的 let obj1: LabelledValue = https://www.it610.com/article/{label:"Size 10 Object"} // 如果将其定义为LabelledValue类型的数据,那么该对象所包含的属性必须跟定义好的接口完全一致 printLabel(myObj) printLabel(obj1)//可选属性 interface Person { name?: string age?: number } function createSquare (config: Person): {color: string; area: number} { let newSquare = {color: "white", area: 100} if (config.color) { newSquare.color = config.color } if (config.width) { newSquare.area = config.width * config.width } return newSquare } let mySquare = createSquare({color: "black"}) /* 好处一:可以对可能存在的属性进行预定义; 好处二:可以捕获引用了不存在的属性时的错误 */ // 只读属性 interface Point { // 一些对象属性只能在对象刚刚创建的时候修改其值,用readonly来指定只读属性 readonly x: number readonly y: number } let p1: Point = {x: 10, y: 20} p1.x = 5; // error // 类类型 实现接口 interface ClockInterface { currentTime: Date setTime(d: Date) // 在接口中描述一个方法,在类里实现它 } class Clock impolements ClockInterface { // 接口描述了类的公共部分,而不是公共和私有两部分。它不会检查类是否具有某些私有成员 currentTime: Date setTime(d: Date) { this.currentTime = d } constructor(h: number, m: number) } // 继承接口一个接口可以继承多个接口 interface Shape { color: string } interface PenStroke { penWidth: number } interface Square extends Shape, PenStroke { sideLength: number } let square ={} // 创建一个对象并指定泛型 square.color = "blue" square.penWidth = 5; square.sideLength = 10;// 混合类型 所谓混合类型就是在一个接口中定义多种类型,比如属性,函数,数组等 interface Counter { (start: number): string interval: number restet(): void } function getCounter(): Counter { let counter = function (start: number) {} counter.interval = 123 counter.reset = function () {} return counter } let c = getCounter() c(10) c.reset() c.interval = 5

四、类
class Greeter { public greeting: string // 设置greeting属性 public constructor (name: string) { console.log(name) this.greeting = name } public greet () { return "Hello" + this.greeting } protected emp () { console.log(`我会被继承`) } } let greeter = new Greeter("world!") /* 修饰符 1、public 默认。类似C#中的public,指定成员可见的意思 2、private 指定它不能在声明它的类的外部访问(子类也不能),就是不能被继承 3、protected 与private类似,但是在子类可以访问,可以被继承 4、readonly 设置为只读属性。只读属性必须在声明时或构造函数里被初始化。 5、static 静态属性。存在于类本身上,而不是类的实例上,所以访问的时候需要加该类名 6、abstract 抽象类。不会被实例化,仅提供继承;用于定义抽象类和在抽象类内部定义抽象方法。 */class Employee extends Greeter { code: String constructor (name: String, code: String) { // 表明实例化时必须传2个参数 super(name) // 调用父类构造函数 this.code = code } work () { super.emp() // 调用父类的emp方法 this.doWork() // 调用当前类的方法 } private doWork () { // 将其定义为私有属性,外部不能调用 console.log("这玩意儿是私有的") } } let employee = new Employee('二狗子', '14') employee.doWork() // 会报错,私有属性不能在外部访问

五、函数
//完整函数类型 let myFun: (value: number, item: number) => number = function (x: number, y: number): number {return x + y} /* 函数类型包含两部分:参数类型和返回值类型; 传递给函数的参数个数必须与函数期望的参数个数一致; 传递的参数名和接收的参数名可以不同,只要参数类型是匹配的就行;接收的参数类型也可以省略不写————推断类型; */// 可选参数 function myFun1 (firstName: string, lastName?: string) {} // 可选参数必须跟在必须参数后面// 默认参数 function myFun2 (firstName: string, lastName = "Smith") {} // 当一个参数没有传或者传递的值是undefined时// 剩余参数 /* 当不知道有多少个参数会传递过来时 */ function myFun3 (firstName: string, ...restOfName: string[]) {} // 剩余参数会被当做个数不限的可选参数。可以没有,也可以有多个。(...) let myFun4: (fname: string, ...rest: string[]) => string = buildName // 也可以在函数类型定义上使用 // this参数 function myFun4 (this: void, name: string) {} // this参数必须放到所有参数的最前面




转载于:https://my.oschina.net/lpcysz/blog/2353351

    推荐阅读