TypeScript相关知识

TypeScript语言

TypeScript 是 JavaScript 的超集,包含了 JavaScript 的所有元素,并扩展了语法。 TypeScript比JavaScript多了类型系统和ES6+ 但是最终都会编译成JavaScript 。TypeScript是强类型的。

TypeScript使用

// 使用typescript  先安装模块:yarn add typescript --dev
// 然后就可以使用tsc的命令来运行文件  yarn tsc  文件名 来编译ts文件

// 也可以使用tsc来编译整个项目;在编译项目之前需要创建一个配置文件:yarn tsc --init```

Flow静态类型检查方案

  1. flow初步使用

yarn add flow-bin --dev
yarn flow init
// a.js文件 flow文件需要在开始的地方加上注释@flow
// @flow
function sum (a:number, b:number) {
  return a + b
}
sum(20, 20)
在终端输入:yarn flow a.js

  1. flow编译去掉注解方法
方法1:
yarn add flow-remove-types --dev
yarn flow-remove-types src -d dist // 当前目录转换到输出目录
方法2
yarn add @babel/core @babel/cli @babel/preset-flow --dev
// 安装上面的依赖之后还需穿件.babelrc配置文件;增加内容为
{
	"presets": ["@babel/preset-flow"]
}

可以使用vscode提供的插件 Flow Language Support 来自动在代码编译阶段就检查。

  1. 类型推断
// @flow
function square (n) { // 没有类型注解
	return n * n
}
square(10) // 100
square('10') // 报语法错误;因为没有定义类型注解;推断为number
  1. 类型注解
// @flow
function foo ():number { // 没有返回值时类型标注为 void
  return 100
}
let num: number = 100
num = 'string'  // 报语法错误

5.原始类型数据

const a: string = 'foobar'

const b: number = 100 // NaN  Infinity

const c: boolean = true // false
// 前面三个是可以为空的 在非严格模式下是可以的;严格模式下是不行的 strict
const g: string = null

const d: null = null

// 一般会在函数没有返回值的时候用来标记这个函数返回值类型
const e: void = undefined  // 在严格模式下只能是undefined;非严格模式下可以是null

const m: undefined = undefined

const f: symbol = Symbol()

Promise
  1. 数组类型
// 数组类型
const arr1: Array<number> = [1,2,3]

const arr2: number[] = [1,2,3]
// 案例
function sum(...args) {
    // 原来的写法需要判断是不是数字类型
    return args.reduce((prev,current) => prev + current,0)
}
function sum1(...args:number[]) {
    // 原来的写法需要判断是不是数字类型;现在直接可以使用类型注解
    return args.reduce((prev,current) => prev + current,0)
}

sum1(1,2,3,4)
  1. 对象类型
// object 不单单指对象在这里;指的是除原始类型以外的其他类型
const foo: object = {}  // [] // function()

// 对象自变量
const obj: { foo: number, bar: string } = { foo: 234, bar: 'hello' }
  1. 函数类型
// 函数的注解直接在参数后面添加就行;函数返回值的注解就在参数圆括号后面写;如果参数是可选参数就需要在参数后面加上一个?,代表可选参数
function fnc1(a: number, b?: number, c: number = 10, ...rest: number[]): string {
  return 'fnc1'
}

fnc1(100)
fnc1(100, 200)

const func2: (a: number, b: number) => string= function (a: number, b: number): string {
    return 'func2'
  }
  1. 任意类型
function stringify(value: any) {
  // 把value序列化成一个json字符串
  return JSON.stringify(value)
}

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

let foo: any = 'string'

foo = true

// any是不安全的


// 隐式类型推断

let age = 19
// age = '19'  // 这里会报错;因为ts已经推断为age为number类型

let foo1   // 如果我们没有咋声明的时候赋值;相当于就是any任意类型的值
foo1 = 'string'

  1. 特殊类型
// @flow
// 字面量类型
const a: 'foo' = 'foo'
// 字面量配合联合类型 ‘|’
const tyoe: 'success' | 'warning' | 'danger' = 'success'
// 联合类型 ‘|’用法
const b: number | string = 100
// type 关键词单独声明
type StringOrNumber = string | number
const b: StringOrNumber = 'string' // 100
// maybe 类型
const gender: ?number = null
const gender: number | null | void = null
// Mixed 类型(强类型)
function passMixed (value: mixed) {
	if (typeof value === 'string') {
  	value.substr(1)
  }
  if (typeof value === 'number') {
  	value * value
  }
}
passMixed('string')
passMixed(100)
// Any 类型(弱类型)
function passAny (value: ang) {
	value.substr(1) 
  value * value 
}
passAny('string')
passAny(100)

TypeScript和上面的flow类似

  • 枚举
// 可以使用enum声明一个枚举;加上const就是常量枚举
// enum PostStatus {
//   // 具体的值;会累加;如果给第一个设置的值是5;第二个就是6;依次累加;如果枚举的值是字符串,就需要给每个成员初始化一个字符串的值。
//   Draft = 0,
//   Unpublished = 1,
//   Published = 2
// }

const enum PostStatus {
  // 具体的值;会累加;如果给第一个设置的值是5;第二个就是6;依次累加;如果枚举的值是字符串,就需要给每个成员初始化一个字符串的值。
  Draft = 0,
  Unpublished = 1,
  Published = 2
}


const post = {
  title: 'Hello TypeScript',
  content: 'TypeScript is a typed superset of JavaScript.',
  status: PostStatus.Draft //3 // 2 // 1 // 0 这个值可以是0,1,2,3的中的一个;代表状态;这个时候就可以使用枚举来做;好处是:可以给一组数值都分别取上一个更好理解的名字;一个枚举中只会存在几个固定的值;不存在超出范围的可能性
}

// PostStatus[0]  // Draft 可以取到Draft这个键

// 当我们确定不会存在通过所引来获取枚举的时候可以使用常量枚举 当我们使用常量枚举的时候就是在枚举前面加上const
  • 类型断言
const nums = [110, 120, 119, 112]

const res = nums.find(i => i > 0)  // 寻找第一个大于0的数字

// res 我们是知道他肯定是一个数字;但是ts认为可能是数字;也可能找不到;是undefined;所以这个时候就需要用到类型断言
const squer = res * res


// 类型断言

const num1 = res as number

const num2 = <number>res  // JSX下不能使用
  • 类型声明
// 在定义的时候没有声明;但是在使用的时候可以单独声明;可以兼容很多js模块(第三方模块)

import { camelCase } from 'lodash'  // 只安装lodash的话就需要下面的声明declare;如果安装了yarn add @types/lodash --dev    就不用下面的declare来声明了
import qs from 'query-string'  // 像这个就自动有类型声明文件直接导入就行了。

// 声明类型 declare关键字
// declare function camelCase(input: string): string

// 转成驼峰式
const res = camelCase('hello typed')
  • 元组类型
const tuple:[number,string] = [10, 'sfy']

// 访问元组中的元素
const age = tuple[0]
const name = tuple[1]

const [age1,name1] = tuple

console.log(age);
console.log(age1);
console.log(name);
console.log(name1);

// ES2017新方法:Object.entries({foo:123,bar:456}) 来得到键值数组;其中每一个键值就是一个元组
  • 类与接口
// 定义接口
interface Eat {
  // 定义成void;就是undefined 在费严格模式下;严格模式下就是null
  eat(food: string): void
}

interface Run {
  run(distance: number): void
}

// 类中使用这个接口
class Person implements Eat, Run {
  // 当函数没有返回值的时候我们应该把他的类型标记为void
  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}`);

  }
}
  • 接口
// 定义接口
interface Post {
  title: string
  content: string
  // 可选成员:在后面加上一个 ?
  subtitle?: string
  // 添加一个只读成员  一个文章中;summary文章摘要;不能修改是只读属性
  readonly summary: string
}

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

}

printPost({
  title: 'hello TypeScript',
  content: '你好啊;我是sfy',
  summary: 'a JavaScript'
})

// 总结:接口就是来约束对象的结构;要实现这个接口;那么这个对象必须要有这个接口所约束的所有成员

// ----------------动态成员的用法
// 例如缓存对象;在运行的时候就会存在一些动态的键值
interface Cache {
  [key: string]: string
}

const cache: Cache = {}
cache.foo = 'value12'
cache.foo1 = 'caldlkjglk'
  • 抽象类
// 定义抽象类  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}`);

  }

}

const d = new Dog()
d.eat('aiyou')
d.run(40)

// 泛型:就是指的是我们在定义函数接口类的时候没有指定具体的类型;在使用的时候在指定

function createNumberArray(length: number, value: number) {
  const arr = Array<number>(length).fill(value)
}

const res = createNumberArray(3, 100)

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

const res1 = createArray<string>(3, 'foo')
  • 类的使用
class Person {
  // 在ts中类的属性必须要有个初始值;要不在定义的时候给出默认值;要不在构造函数里面写入初始值
  name: string
  // 我们可以在类中添加访问修饰符:例如添加private之后就是代表着私有的;默认都是共有成员public
  private age: number  // 私有属性
  // protected代表受保护的访问修饰符 ;也不能在外部访问;但是可以在子类中访问对应的成员
  // readonly 代表着只读属性
  protected readonly gender: boolean

  constructor(name: string, age: number) {
    this.name = name
    this.age = age
    this.gender = true
  }
  sayHi(msg: string) {
    console.log(`I am ${this.name},${this.age}岁`);
    console.log(this.age);

  }
}

class Student extends Person {
  constructor(name: string, age: number) {
    super(name, age)
    console.log(this.gender);

  }
}

const tom = new Person('tom', 18)
console.log(tom.name);
// console.log(tom.age);  // 这里会报错;因为age是私有属性
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值