TypeScript初步学习

为什么80%的码农都做不了架构师?>>>   hot3.png

一、安装使用

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文件

    把项目主文件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 = {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

你可能感兴趣的:(TypeScript初步学习)