Typescript语言

目录

类型

弱类型缺点

强类型优点

Flow

概念

使用

如何去掉类型注解

对象类型

函数类型

特殊类型

mixed和any类型

flow官方文档和类型手册

运行环境API

Typescript

概念

缺点

使用

原始类型

标准库声明

作用域问题

一些类型

class


类型

  1. 强类型VS弱类型,强类型不允许隐式转换,弱类型可以;
  2. 静态类型VS动态类型,静态类型就是声明时就明确了类型,并且一旦声明后类型不能修改;动态类型是运行时才知道类型,并且声明后类型可以被修改;
  3. Javascript是一种弱类型的动态语言

弱类型缺点

  • 类型错误需等到运行时才能抛出异常
  • 参数的类型可能导致函数的功能与预期不符
  • 对象属性名使用发生错误
    var obj = {};
    obj[true] = true;
    console.log(Obj["true"])//true

     

强类型优点

  • 更早发现错误
  • 开发更智能,编码更准确,减少不必要的类型判断
  • 方便重构

Flow

概念

  • Javascript的类型检查器,通过给参数增加类型注解,可以避免参数不明确带来的问题

 

使用

下载flow-bin

初始化flow: flow init

使用,在文件中加一个注释@flow, 然后在需要的地方添加类型注解

 

如何去掉类型注解

1. flow官方提供

下载flow-remove-types

使用flow-remove-types xx当前文件相对路径 -d xx去掉类型注解后的文件相对路径

2. babel

下载@babel/cli @babel/core @babel/preset-flow

使用  babel xxx当前文件目录 -d xxx去掉类型注解后的文件目录

  • Flow Language Support(VScode提供的flow插件)
  • flow会根据使用情况判断类型,最好还是为参数添加类型注解
  • 支持的原始类型
/**
 * 原始类型
 *
 * @flow
 */

const a: string = 'foobar'

const b: number = Infinity // NaN // 100

const c: boolean = false // true

const d: null = null

const e: void = undefined//这个在函数中也是一样

const f: symbol = Symbol()

对象类型

/**
 * 对象类型
 *
 * @flow
 */

const obj1: { foo: string, bar: number } = { foo: 'string', bar: 100 }

const obj2: { foo?: string, bar: number } = { bar: 100 }

const obj3: { [string]: string } = {}

obj3.key1 = 'value1'
obj3.key2 = 'value2'

函数类型

/**
 * 函数类型
 *
 * @flow
 */

function foo (callback: (string, number) => void) {
  callback('string', 100)
}

foo(function (str, n) {
  // str => string
  // n => number
})

特殊类型

/**
 * 特殊类型
 *
 * @flow
 */

// 字面量类型

const a: 'foo' = 'foo'

const type: 'success' | 'warning' | 'danger' = 'success'//组合类型

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

// 声明类型

type StringOrNumber = string | number

const b: StringOrNumber = 'string' // 100

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

// Maybe 类型

const gender: ?number = undefined
// 相当于
// const gender: number | null | void = undefined

mixed和any类型

/**
 * Mixed
 *
 * @flow
 */

//mixed就相当于所有类型的混合,仍然属于强类型 string | number | boolean | ....
function passMixed (value: mixed) {
  if (typeof value === 'string') {
    value.substr(1)
  }

  if (typeof value === 'number') {
    value * value
  }
}

passMixed('string')

passMixed(100)
//any的用法类似,但是any是一种弱类型,是为了兼容老版本而出现的,不建议使用

flow官方文档和类型手册

运行环境API

 

Typescript

概念

是一种强类型的静态语言,Javascript的超集,在Javascript的语言基础上拓展了一些特性,开发完成后再编译成JavaScript代码,任何一种JavaScript的运行环境都支持

缺点

  • 语言本身多了很多概念
  • 开发初期,成本较高,但对于大型项目,利大于弊

使用

  • 下载包 

npm i typescript --save-dev

  • 生成tsc命令

(相当于typescript compile),可以使用该命令把一个ts文件编译成一个js文件( tsx xxxx.ts )

  • 配置文件

可以使用tsconfig.json文件来配置编译选项(使用 tsc --init 即可生成)

下面是一些主要的配置选项

target: 编译后采用那个es版本

module: 生成模块使用哪种方式

sourceMap:源代码映射

outDir:编译后生成文件目录

rootDir:需要编译的文件目录

strict: 是否启用严格模式

 

原始类型

// 原始数据类型

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()

// Promise

// const error: string = 100

标准库声明

标准库声明就是内置对象对应声明

比如,Symbol就是es2015的内置对象,因此当你tsconfig.json中lib选项和tatget选项没有es2015,在代码中写入Symbol()就会报错,因为缺少标准库声明,lib中加上标准库es2015就不会报错了

作用域问题

typescript不允许全局作用域中存在相同变量,因此一般把相同的变量放在不同作用域中

一些类型

  • 对象类型
// Object 类型

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

// 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
  • 元组类型(固定元素类型和数量)
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
  • 枚举类型(某个属性可以有多个确定的值)

js

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

ts

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

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

枚举会侵入编译结果,生成双向键值

使用常量枚举可以解决

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

编译结果:直接生成对应的值

  • 函数类型
//函数表达式
const func2: (a: number, b: number) => string = function (a: number, b: number): string {
  return 'func2'
}
//函数声明
function func1 (a: number, b: number = 10, ...rest: number[]): string {
  return 'func1'
}

func1(100, 200)
  • 尽量不要使用任意类型(any)
  • 隐式类型推断
let age = 18 // number

// age = 'string'   被推断为number了,此处报错
  • 类型断言( as / 尖括号<>)
const num1 = res as number

const num2 = <number>res // JSX 下不能使用
  • 接口(interface),约定成员类型, 编译时会忽略掉
interface Post {
  title: string
  content: string
  subtitle?: string//可选
  readonly summary: string//只读
}

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

interface Cache {
  [prop: string]: string//动态成员
}

const cache: Cache = {}

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

class

  • 概念
class Person {
  public name: string // = 'init name'// 公共成员,可以被继承,可以被外部访问
  private age: number//私有成员,不能被继承,不能被外部访问
  // 只读成员 readonly
  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}`)
  }
}
  • 抽象类

和接口一样去限制类型,但是只能被继承,不能直接new

//抽象类 类之前加abstract关键字,只能被继承,不用实现
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)
  }

}

//new 一个子类
const d = new Dog()
//具备抽象方法,以及抽象类中的其他方法
d.eat('嗯西马')
d.run(100)
  • 泛型(generic)

声明时把不明确的类型定义<T>,使用的时候传入参数

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

const res = createArray<string>(3, 'foo')
  • 类型声明

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值