Part1-2-2 TypeScript 语言

 

弱类型的问题

// JavaScript 弱类型产生的问题

// 1. 异常需要等到运行时才能发现

const obj = {}

obj.foo()

setTimeout(() => {
  obj.foo()
}, 1000000)

// =========================================

// 2. 函数功能可能发生改变

function sum (a, b) {
  return a + b
}

console.log(sum(100, 100))
console.log(sum(100, '100'))

// =========================================

// 3. 对象索引器的错误用法

const obj = {}

obj[true] = 100 // 属性名会自动转换为字符串

console.log(obj['true'])

 

强类型的优势

错误更早暴露

代码更智能、编码更准确

重构更牢靠

减少不必要的类型判断

 

原始类型

// 原始数据类型

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

Promise

 

设置中文错误消息

Part1-2-2 TypeScript 语言_第1张图片

 

Part1-2-2 TypeScript 语言_第2张图片

 

Part1-2-2 TypeScript 语言_第3张图片

 

 

Object 类型

object 类型并不是单指 对象,还包括数组,函数

// Object 类型



// object 类型是指除了原始类型以外的其它类型
const foo: object = function () {} // [] // {}

// 如果需要明确限制对象类型,则应该使用这种类型对象字面量的语法,或者是「接口」
const obj: { foo: number, bar: string } = { foo: 123, bar: 'string' }

 

数组类型

// 数组类型



// 数组类型的两种表示方式

const arr1: Array = [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

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

const entries: [string, number][] = Object.entries({
  foo: 123,
  bar: 456
})

const [key, value] = entries[0]
// key => foo, value => 123

 

枚举类型

// 枚举(Enum)



// 用对象模拟枚举
// const PostStatus = {
//   Draft: 0,
//   Unpublished: 1,
//   Published: 2
// }

// 标准的数字枚举
// enum PostStatus {
//   Draft = 0,
//   Unpublished = 1,
//   Published = 2
// }

// 数字枚举,枚举值自动基于前一个值自增
// enum PostStatus {
//   Draft = 6,
//   Unpublished, // => 7
//   Published // => 8
// }

// 字符串枚举
// enum PostStatus {
//   Draft = 'aaa',
//   Unpublished = 'bbb',
//   Published = 'ccc'
// }

// 常量枚举,不会侵入编译结果
const enum PostStatus {
  Draft,
  Unpublished,
  Published
}

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

// PostStatus[0] // => Draft

 

函数类型

// 函数类型



// 函数参数 加 ? 说明参数可选,设置默认值 也成为 可选参数
// function func1 (a: number, b?: number): string {
// function func1 (a: number, b: number = 10): string {
function func1 (a: number, b: number = 10, ...rest: number[]): string {
  return 'func1'
}

func1(100, 200)

func1(100)

func1(100, 200, 300)

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

const func2: (a: number, b: number) => string = function (a: number, b: number): string {
  return 'func2'
}

 

任意类型

// 任意类型(弱类型)



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

stringify('string')

stringify(100)

stringify(true)

let foo: any = 'string'

foo = 100

foo.bar()

// any 类型是不安全的

 

隐式类型推断

TypeScript 会根据变量的使用情况推断出变量的类型

// 隐式类型推断



let age = 18 // number

// age = 'string'

let foo

foo = 100

foo = 'string'

// 建议为每个变量添加明确的类型标注

 

类型断言

// 类型断言



// 假定这个 nums 来自一个明确的接口
const nums = [110, 120, 119, 112]

const res = nums.find(i => i > 0)

// const square = res * res

const num1 = res as number

const num2 = res // JSX 下不能使用

 

接口

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



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

interface Post {
  title: string
  content: string
  subtitle?: string
  readonly summary: string
}

const hello: Post = {
  title: 'Hello TypeScript',
  content: 'A javascript superset',
  summary: 'A javascript'
}

// hello.summary = 'other'

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

interface Cache {
  [prop: string]: string
}

const cache: Cache = {}

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

类的基本使用

// 类(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}`)
  }
}

 

类的访问修饰符

// 类的访问修饰符


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)
console.log(tom.name)
// console.log(tom.age)      // 不可访问
// console.log(tom.gender)  // 不可访问

const jack = Student.create('jack', 18)

 

类的只读属性

只读属性修饰的成员必须在 声明时初始化 或者 在构造函数里赋值,二者只能选其一

// 类的只读属性



class Person {
  public name: string // = 'init name'
  private age: number
  // 只读成员
  protected readonly 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)
  }
}

const tom = new Person('tom', 18)
console.log(tom.name)
// tom.gender = false

 

类与接口

不同的类之间可能也会有相同的行为,这些相同的行为可以用接口定义

// 类与接口



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(length).fill(value)
  return arr
}

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

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

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

const res = createArray(3, 'foo')

 

类型声明

// 类型声明

import { camelCase } from 'lodash'
import qs from 'query-string'

qs.parse('?key=value&key2=value2')

// declare function camelCase (input: string): string

const res = camelCase('hello typed')

 

1

你可能感兴趣的:(大前端学习笔记)