7-TypeScript(01-02-04)

118 阅读1分钟

TypeScript

区别

JavaScript 与 TypeScript 的区别 TypeScript 是 JavaScript 的超集,扩展了 JavaScript 的语法,因此现有的 JavaScript 代码可与 TypeScript 一起工作无需任何修改,TypeScript 通过类型注解提供编译时的静态类型检查。

TypeScript 可处理已有的 JavaScript 代码,并只对其中的 TypeScript 代码进行编译。

安装

// 安装包
npm install typescript
// 编译
tsc filename.ts
// 配置 出现tsconfig.ts 文件
tsc  --init

{
  "compilerOptions": {
   "lib" : ["ES2015", "DOM", "ES2017"],
   "module": "commonjs", 
   // 配置编译目标时使用的模块化标准
   "outDir": "./dist", 
   // 编译结果的文件夹
   "rootDir": "src", 
    "strict": true, 
   "target": "es6"  
   // 配置编译时目标使用的代码标准
  },
  "include": ["./src"]  
  // 编译的文件夹
  // "files": ["./src/index.ts"]    
  // 编译某一个文件
}

可以完全按照 JavaScript 标准语法编写代码

const hello = (name: any) =>  {
  console.log(`Hello, ${name}`)
}

hello('TypeScript')

原始数据类型

const a: string = 'foobar'
const b: number = 100 // NaN Infinity
const c: boolean = true // false
// 在非严格模式(strictNullChecks)下,
// string, number, boolean 都可以为空
// const d: string = null
// const d: number = null
// const d: boolean = null

const e: void = undefined
const f: null = null
const g: undefined = undefined

// Symbol 是 ES2015 标准中定义的成员,
// 使用它的前提是必须确保有对应的 ES2015 标准库引用
// 也就是 tsconfig.json 中的 lib 选项必须包含 ES2015
const h: symbol = Symbol()

作用域问题

默认文件中的成员会作为全局成员 多个文件中有相同成员就会出现冲突

解决办法1: IIFE 提供独立作用域
(function () {
   const a = 123
})()

// 解决办法2: 在当前文件使用 export,也就是把当前文件变成一个模块
// 模块有单独的作用域
const a = 123

export {}

Object 类型

// object 类型是指除了原始类型以外的其它类型
const foo: object = function () {} // [] // {}
// 如果需要明确限制对象类型,则应该使用这种类型对象字面量的语法,或者是「接口」
const obj: { foo: number, bar: string } = { foo: 123, bar: 'string' }

数组类型

// 数组类型的两种表示方式
const arr1: Array<number> = [1, 2, 3]
const arr2: number[] = [1, 2, 3]

// 如果是 JS,需要判断是不是每个成员都是数字
// 使用 TS,类型有保障,不用添加类型判断
function sum (...args: number[]) {
  return args.reduce((prev, current) => prev + current, 0)
}

sum(1, 2, 3) // => 6

元组(Tuple)固定长度 结构

const tuple: [number, string] = [18, 'zce']
const age = tuple[0]
const name = tuple[1]

const [age, name] = tuple

枚举(Enum)

const enum PostStatus {
   Draft = 0,
   Unpublished = 1,
   Published = 2
 }
 
const post = {
  title: 'Hello TypeScript',
  content: 'TypeScript is a typed superset of JavaScript.',
  status: PostStatus.Draft // 3 // 1 // 0
}

函数类型

function func1 (a: number, b: number = 10, ...rest: number[]): string {
  return 'func1'
}
func1(100, 200)
func1(100)
func1(100, 200, 300)

任意类型(弱类型)

any 类型是不安全的
function stringify (value: any) {
  return JSON.stringify(value)
}
stringify('string')
stringify(100)
stringify(true)

接口

interface Post {
  title: string
  content: string
}

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

printPost({
  title: 'Hello TypeScript',
  content: 'A javascript superset'
})

可选成员、只读成员、动态成员

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

// 对象的key必须是string
interface Cache {
  [prop: string]: string
}
const cache: Cache = {}

cache.foo = 'value1'
cache.bar = 'value2'

基本使用

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}`)
  }
}

类的访问修饰符

class Person {
  public name: string // = 'init name'
  private age: number
  protected gender: boolean //只允许子类访问
  
  constructor (name: string, age: number) {
    this.name = name
    this.age = age
    this.gender = true
  }

  sayHi (msg: string): void {
    console.log(`I am ${this.name}, ${msg}`)
    console.log(this.age)
  }
}

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 tom = new Person('tom', 18)
const jack = Student.create('jack', 18)

类与接口

  • 不包含具体的实现
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 class Animal {
  eat (food: string): void {
    console.log(`呼噜呼噜的吃: ${food}`)
  }

  abstract run (distance: number): void
}

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

const d = new Dog()
d.eat('嗯西马')
d.run(100)

泛型

不指定具体的类型,传入的时候确定类型

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 res = createArray<string>(3, 'foo')