TypeScript 基础整理

224 阅读6分钟

快速上手

  1. yarn init --yes
  2. yarn add typescript --dev
  3. yarn tsc path // 文件
  4. 编译好的注解会自动去掉

配置文件

生成配置文件:

yarn tsc --init 生成 tsconfig.js 配置文件

tsconfig.js 配置文件内

{
 "target": "es5",  // 输出转换位哪种特性的语法
 "module": "common.js" // 输出的代码会才用什么样的方式进行模块化,目前使用的是 common.js ,就是导入导出会使用 require 方式进行引用输出
 "outDir": "./"  // 来设置编译结果输出的文件夹
 "rootDir": "./",  // 用来设置原代码的文件夹
 "sourceMap": true, // 设置为 true 时,开启源代码映射, 开启后, 可以通过调试 souceMap 文件来进行测试, 
 "strict": true, // 严格模式, 作用是开启所有严格检查模式选项, 在严格模式下需要为每个类型增加一个注解,没有的话会报错
 
}

通过 yarn tsc path 指定文件时, 配合文件 tsconfig.js 不会生效, 运行 yarn tsc 会生效

TypeScript 6中原始数据类型

 const a: string = "foo"
 const b: number = 100 // NaN Infinity
 const c: boolean = true // false
//  const e: void = null  // 严格模式下只能为 undefined
 const e: void = undefined
 const f: null = null 
 const g: undefined = undefined
 const h: symbol = Symbol()  // 报错  es6当中新增的, ES5 代码库中没有, 解决方法两种, 1.target 值改为 es2015  2.将 es2015 添加到 libs 标准库选项中
// 标准库就是内置对象对应的声明

TypeScript 中文错误消息

yarn tsc --local zh-CN

TypeScript 作用域问题

两个同目录的文件夹内,定义相同的变量会报错,解决方式如下:

//  1.立即执行函数
// (function(){
//   const a = 123
// })()

// 使用 export
const a = 123

export {}

TypeScript Object 类型

object 类型不只指对象{},而是原始数据类型之外的其他类型

export {} // 确保跟其他示例没有成员冲突

// object 类型不只指对象, 而是除了原始数据类型之外的其他类型
 const foo: object =  function(){} // {} // []
//  对象字面量方式, 不推荐使用。 推荐使用接口方式, 下面介绍
 const obj:{foo:number, bar:string} = {foo:123,bar:"123"} // 结构必须完全一样

TypeScript 数组类型

// 和 flow 模式完全一样
// export {}
const arr1: Array<number> = [1]
const arr2: number[] = [2,3,4]

// --------------------

function sum(...args: number[]){
  return args.reduce((prev,current) => prev + current + 0)
}
sum(1,2,3)

TypeScript 元祖类型

元祖类型:一种特殊的数据结构,元祖就是明确元素数量以及每个元素类型的数组

// 对象字面量的形式进行定义
 const tuple: [number,string] = [1,'2']

//  const age = tuple[0]
//  const name = tuple[1]

 const [age,name] = tuple

TypeScript 函数类型

javaScript 中有两种定义函数的方式, 一种是函数声明, 一种是函数表达式,函数声明较为简单


// 函数声明
 function func1(a:number,b:number,c?:number,...rest:number[]): string{
    return 'func1'
 }
// 参数个数也必须完全相同, 参数会按照位置进行传递
 func1(1,2)
func1(100,200,300)

// 函数表达式. 和下面一样
const func2 = function(a:number,b:number):string{
  return 'func2'
}

// 函数表达式
const func3:(a:number,b:number)=>string = function(a:number,b:number):string{
  return 'func2'
}

TypeScript 任意类型

function stringify(value:any){
  return JSON.stringify(value)
}

stringify('string')
stringify(100)
stringify(true)

let foo:any = 'string'
foo = 100
foo.bar()  // 语法上不会报错, 注意是语法上

TypeScript 隐式类型推断

let age = 18 // 此时age 设置为 number 类型

age = "string" // 语法报错, 因为age已经被隐式类型推断为 number

let foo    // foo 被推断为 any 类型
foo = 100  // 都不会报错
foo = "string" // 都不会报错

TypeScript 类型断言

js 断言方式有两种, 一种是 as 的方式, 一种是 <> 方式, <> 方式在jsx 中不能使用, 会有语法冲突

// 假定这个 nums 来自一个明确的接口

const nums = [100, 200, 300,400]
const res = nums.find(i => i > 0) // 返回值为 number 或 undefind

// 类型断言方式有两种
// 一种 as 方式
const  num1 = res as number

// 一种尖括号方式<>
const num2 = <number>res // jsx 下不能使用

TypeScript 接口 interface

接口 可以理解为一种规范, 或者一种契约,抽象的概念


interface Post {
  title:string
  content: string
  subtitle?: string // 可选成员
 readonly summary: string // 只读成员
}

function printPoint(post: Post){
  console.log(post.title)
  console.log(post.content)
}

printPoint({
  title:"interface",
  content: "hello",
  summary:"摘要"
})


// ----------------
// 动态成员
interface Cache {
  [prop:string]:string
}
const cache:Cache = {}

cache.foo = 'value'
cache.age = 2  //  报错,所有的成员为 string 类型

TypeScript 类Classes

类的作用可以用来描述一类事物的抽象特征,用来描述一类对象的抽象成员 , ES6 之前函数 + 原型 模拟实现类,ES6 开始,javaScript 中有了专门的 class, TypeScript 增加了 class 的相关语法


class Person {
 name: string  // = 'init name' // 类属性在使用之前,必须现在类型中声明, 目的为了给类的属性增加标注
 age: number  // 类的属性必须要有一个初始值, 可以通过 = 去赋值 , 活在在构造函数中初始化
 constructor (name: string, age:number){
   this.name = name
   this.age =age
 }
 sayHi(msg: string): void{
   console.log(`I am ${this.name}, ${msg}`)
 }
}

TypeScript 类的访问修饰符

三个访问修饰符, public private protected 用来控制类当中的成员可访问级别。

class Person {
  public name: string  // = 'init name' // 类属性在使用之前,必须现在类型中声明, 目的为了给类的属性增加标注
  private age: number  // 类的属性必须要有一个初始值, 可以通过 = 去赋值 , 活在在构造函数中初始化
  protected gender: boolean // protected 受保护的, 指的是,只允许再子类中访问
  constructor (name: string, age:number){
    this.name = name
    this.age = age
    this.gender = true
  }
  sayHi(msg: string): void{  // TypeScript 中的void 是一个正确的类型,告诉开发人员这个函数返回 undefined
    console.log(`I am ${this.name}, ${msg}`)
  }
}

const tom = new Person('tom',18)
console.log(tom.name)
// console.log(tom.age)  // 报错
//  console.log(tom.gender) // 报错。 gender 受保护的

 class Student extends Person {
  private constructor (name: string, age: number){
      super(name, age)
      console.log(this.gender)
   }
  static create(name:string,age:number){
    return new Student(name,age)
  }
 }
 
 const jack = Student.create('jack', 18)

TypeScript 类的只读属性

readonly 只读属性 , 在能在内部赋值 , 不能修改

TypeScript 类与接口

// 接口越简单越好
interface Eat { 
  eat(food:string):void
}
interface Run {
  run(distance: number): void
}

class Person implements Eat,Run{
  eat(food:string):void{
    console.log(`优雅进餐: ${food}`)
  }
  run(distance:number){
    console.log(`直立行走: ${distance}`)
  }
}

class Animal implements Eat,Run {
  eat(food:string):void{
    console.log(`呼噜 ${food}`)
  }
  run(distance:number){
    console.log(`爬行 ${distance}`)
  }
}

类 抽象类

抽象类在某种程度上和接口有点相似, 不同的是,抽象类可以包含一些具体的实现,接口不包含具体的视线, 一般大类用抽象类, 比如动物类

// abstract 只能继承不能通过new 的方式创建
abstract class Animal {
  eat(food:string):void{
    console.log(`呼噜吃:${food}`)
  }
  abstract run (distance: number):void  // 父类要是有 abstract 的, 子类必须要实现
}

class Dog extends Animal {
  run(distance: number): void {
    console.log(`四角爬行`, distance)
  }
}

const d = new Dog()
d.eat('草')
d.run(100)

TypeScript 泛型 Generics

泛型就是指我们在定义函数或类的时候, 在声明时没有定义指定的类型。 通过传参的形式来实行

 function createNumberArray(length: number,value:number):number[]{
   const arr = Array<number>(length).fill(value)
   return arr
 }
 function createStringArray(length: number,value:string):string[]{
  const arr = Array<string>(length).fill(value)
  return arr
}

function createArray<T>(length: number,value:T):T[]{
  const arr = Array<T>(length).fill(value)
  return arr
}

 const res = createNumberArray(3,100)
 // res => [100,100,100]

 const res2 = createArray<string>(3,'2')

TypeScript 类型声明(Type Declaration)

TypeScript 中引入第三方模块, 需要引入对应的声明文件, 没有的话需要自己定义

import { camelCase } from 'loadsh'

declare function camelCase (input:string): string  // 定义对应的模块
const res = camelCase('hello typed')


 export {} // 确保跟其他示例没有成员冲突