TypeScript初步学习
为什么80%的码农都做不了架构师?>>>
文章图片
一、安装使用
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
推荐阅读
- 由浅入深理解AOP
- 继续努力,自主学习家庭Day135(20181015)
- python学习之|python学习之 实现QQ自动发送消息
- 一起来学习C语言的字符串转换函数
- 定制一套英文学习方案
- 漫画初学者如何学习漫画背景的透视画法(这篇教程请收藏好了!)
- 《深度倾听》第5天──「RIA学习力」便签输出第16期
- 如何更好的去学习
- 【韩语学习】(韩语随堂笔记整理)
- 焦点学习田源分享第267天《来访》