菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
0
0

30分钟入门TypeScript

原创
05/13 14:22
阅读数 140

接下来,TypeScript我会简称为ts

1.预备环境:

安装node.js全局安装

typeScript:npm i -g typescript

2. 配置文件tsconfig.json

这里是ts编译器配置文件常用的配置项,该配置项在webpack也将使用,了解即可

{
  /* ts 配置文件 */
  // 哪些TS文件需要被编译
  "include": [
    // 根目录下src目录下任意目录的任意文件都会被编译
    // ** 任意目录
    // * 任意文件
    "./src/**/*"
  ],
  // 哪些TS文件不需要被编译
  "exclude": [],
  // 定义被继承的配置文件
  // "extends": [],
  // 编译哪些文件,写文件名,一般用不上
  // "files": [],
  // 编译器选项
  "compilerOptions": {
    // ts被编译的es版本
    "target": "ES6",
    // 指定使用模块化规范
    "module": "amd",
    // 指定项目中要使用的库,一般不用修改此配置
    // "lib": ["DOM"]
    // 指定编译后文件所在的目录
    "outDir": "./dist",
    // 将全局作用域代码合并为一个文件
    "outFile": "./dist/app.js",
    // 是否对js文件进行编译
    "allowJs": false,
    // 检查js代码是否符合语法规范
    "checkJs": false,
    // 是否移除注释
    "removeComments": false,
    // 不生成编译后的文件
    "noEmit": false,
    // 当有错误时不生成编译后的文件
    "noEmitOnError": false,
    // 设置编译后的文件使用严格模式
    "alwaysStrict": true,
    // 所有严格检查的总开关
    // "strict": true,
    // 不允许隐式any类型
    "noImplicitAny": false,
    // 不允许不明确的this
    "noImplicitThis": true,
    // 严格检查空值
    "strictNullChecks": true
  }
}

3. webpack打包ts

这里讲解简单搭建一个webpack打包环境,稍作了解即可。

1.段落引用生成webpack配置文件:npm init -y
2.段落引用下载webpack常用依赖:npm i -D webpack webpack-cli typescript
3.段落引用ts-loader根目录创建webpack配置文件:webpack.config.js,配置文件种编码如下:

const path = require('path')
module.exports = {
  // 指定入口文件
  entry: './src/index.ts',
  // 指定打包文件所在目录
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  // 指定webpack打包时要使用的模块
  module: {
    // 指定加载规则
    rules: [
      {
        test: /\.ts$/,
        use: 'ts-loader',
        exclude: /node-modules/
      }
    ]
  },
  mode: 'development'
}

4.创建ts配置文件 tsconfig.json #
5.在package.json添加脚本

"scripts": {
    "build": "webpack"
  }

一个简单的打包工具就这样构建好了,然后执行npm run build 就可以进行打包了

4. 使用vscode插件运行ts

该方式用来快速搭建一个ts运行环境,可以暂时不去接触各类打包工具,方便我们快速去尝试ts编程。

1.vscode安装run code插件
2.安装ts-node npm install -g ts-node
3.在.ts文件中右击选择 Run Code 即可运行当前文件的ts代码

5. 各种类型声明

类型声明,内容不多,请认真牢记,方便后续编写代码

let a: number
a = 10
a = 20
a = '123' // 会报错 不能将类型“string”分配给类型“number”

// 声明和赋值同时进行,会自动推断类型
let b = false
b = 123 // 会报错 不能将类型“number”分配给类型“boolean”

// 函数参数类型声明 返回值声明类型
function sum (a: number, b: number) : number {
  return a + b
}
sum(1, '2') // 类型不对会报错
sum(1, 2) // 正确调用

// 字面量类型声明 联合类型
let c: 'apple' | 'orange' | 'banana'
let d: boolean | string | number

c = 'apple'
c = 'orange'
// c = 'dog' // 报错 不能将类型“"dog"”分配给类型“"apple" | "orange" | "banana"

// any类型可设置任何值
let e: any
e = 1
e = '1'
e = false

// unknown 未知类型
let f: unknown
f = 1
f = '1'
f = false

// any 和 unknown 的区别
// any可以赋值给任何变量,可能会影响其它变量的类型

// 断言:告诉编译器实际类型
let g = f as string // 变量 as 类型
let h = <string>g // <类型>变量

// void 表示空,如果用在函数,表示没有返回值
function fn (): void {
  return undefined
}

// never 表示永远不会返回结果
function fn2 (): never {
  throw new Error('报错了')
}

// 定义一个对象
let i: object
// 指定对象中可以包含哪些属性
let j: { name: string, age?: number } // 该对象只允许有name属性,可选属性是age

let k: { name: string, [propName: string]: any } // [propName: string]: any 表示任意属性

// 定义函数的类型和返回值类型
let l: (a: number, b: number) => number

// 定义一个数组
let m: string[]
let m1: Array<number>
m = ['1', '2', '3']
m1 = [1, 2, 3]

// 元组:固定长度的数组
let n: [string, string]

// 枚举:列举出所有可能性
enum Gender {
  Male,
  Female
}
let o: { name: string, gender: Gender }
o = {
  name: '杨超越',
  gender: Gender.Male
}

// 类型别名
type MyType = { name: string, gender: Gender }
let p: MyType
p = {
  name: '杨超越',
  gender: Gender.Male
}

6. 类(Class)

创建类通常的书写范式如下:

class 类名 {
  属性名: 类型
  constructor (参数: 类型) {
    this.属性名 = 参数
  }
  方法名 () {
    // do something
  }
}

下面是个小栗子,包含类的属性、只读属性、静态属性和方法、构造函数。

class Person {
  // 属性
  name: string
  age: number = 18
  // 只读属性
  readonly gender: string = '男'
  // 定义静态属性
  static weight: number = 120

  // 构造函数 在对象创建时调用
  constructor (name: string) {
    this.name = name
  }

  // 定义方法
  // 普通方法
  sayHello (): void {
    console.log('hello typescript')
  }
  // 静态方法
  static sayHi (): void {
    console.log('hi typescript')
  }
}

const person = new Person('胡歌')
console.log(person.name) // 胡歌
console.log(person.age) // 18
console.log(person.gender) // 男
person.sayHello() // 'hello typescript
console.log(Person.weight) // 120
Person.sayHi() // hi typescript

7. 继承

ts中的继承和es6大同小异,看一下案例即可掌握。

class Animal {
  name: string
  age: number
  constructor (name: string, age: number) {
    this.name = name
    this.age = age
  }
  say (): void {
    console.log('animal speak')
  }
}

class Dog extends Animal {
  say (): void {
    console.log('wang wang wang ~')
  }
}

class Cat extends Animal {
  // 如果子类加了构造函数
  // 那么构造函数内必须调用一下父类构造函数
  // super即可调用父类构造函数
  constructor (name: string, age: number) {
    super(name, age)
  }
  say (): void {
    console.log('miao miao miao ~')
  }
}

const dog = new Dog('旺财', 2)
const cat = new Cat('咪咪', 1)

dog.say() // wang wang wang ~
cat.say() // 'miao miao miao ~

8. 抽象类 and 抽象方法

如果不希望有人去实例化父类,那么可以用关键字 abstract 创建类,那这个类就是抽象类。
如果这个方法没有方法体,并用abstract 修饰,且只能写在抽象类中,且必须被子类重写,那这个方法就是抽象方法。

abstract class People {
  name: string
  age: number
  constructor (name: string, age: number) {
    this.name = name
    this.age = age
  }
  // 定义抽象方法,没有方法体,只能写在抽象类中,且必须被子类重写
  abstract say (): void
}
// const zhangsan = new People() // 会报错:无法创建抽象类的实例

9. 接口

接口可以当类型声明使用。

interface MyInterface {
  name: string,
  age: number
}
const obj: MyInterface = {
  name: '222',
  age: 18
}

接口也可以用来定义类的结构。

interface MyInter {
  name: string,
  speak (): void
}

class MyClass implements MyInter {
  name: string
  constructor (name: string) {
    this.name = name
  }
  speak (): void {
    console.log('hello ts')
  }
}

总结一下,接口就是为了定义规范,对类进行限制以满足某种使用场景需求。

10. 属性修饰符

1.public 修饰属性可以在任意位置访问(默认)
2.private 私有属性 只能在类内部访问
3.protected 受保护的属性 只能在当前类和其子类中访问
4.get 设置getter方法
5.set 设置setter方法

class Person {
  private name_: string
  private age_: number
  constructor (name: string, age: number) {
    this.name_ = name
    this.age_ = age
  }
  getString () {
    return {
      name: this.name_,
      age: this.age_
    }
  }
  // 设置getter方法
  get name () {
    return this.name_
  }
  // 设置setter方法
  set name (value: string) {
    this.name_ = value
  }
}
const per = new Person('张三', 18)
// per.age // 错误的调用方式,会报错:属性“age”为私有属性,只能在类“Person”中访问
console.log(per.getString()) // { name: '张三', age: 18 }
per.name = '孙悟空'
console.log(per.name) // 孙悟空

11. 泛型

在定义函数或者类时,如果遇到类型不明确的情况可以使用泛型
在一个方法上使用泛型:

function fn<T> (a: T): T {
  return a
}
fn<string>('hello')
fn<number>(10)

也可以指定多个泛型:

function fn2<T, K> (a: T, b: K): T {
  console.log(b)
  return a
}
fn2<number, string>(1, '2')

可以通过接口限制泛型:

interface Inter {
  length: number
}
function fn3<T extends Inter> (a: T): number {
  return a.length
}
fn3('123')

在类中定义泛型:

class MyClass<T> {
  name: T
  constructor (name: T) {
    this.name = name
  }
}
const mc = new MyClass<string>('张三')

发表评论

0/200
0 点赞
0 评论
收藏