1.解决JavaScript类型系统的问题
2.大大提高代码的可靠程度
3.语言本身多了很多概念
4.项目初期,TypeScript会增加一些成本(适合长期大项目)
1.强类型与弱类型(类型安全)
(1)语言层面限制函数的实参类型必须与形参类型相同
(2)强类型有更强的类型约束,而弱类型中几乎没有什么约束
(3)强类型语言中不允许任意的隐式类型转换 而弱类型允许
2.静态类型与动态类型(类型检查)
(1)静态类型:一个变量声明时它的类型就是明确的 声明过够,它的类型就不允许更改了
(2)动态类型:运行阶段才能够明确变量类型 而且变量的类型可以随时变化
1.弱类型且动态类型
2.缺乏类型系统可靠性
(1)型异常需要等到运行时才能够被发现
(2)类型不明确会导致函数功能发生改变
1.错误更早的发现 在编码阶段
2.代码更加智能、准确
3.重构更加牢靠
4.减少不必要的类型判断
1.JavaScript的类型检查器
yarn add flow-bin --dev //下载flow
flow init // 创建 flowconfig文件命令
2.flow-bin的移除类型注解的插件
(1)flow-remove-types 官方提供的移除类型的插件
命令:yarn flow-remove-types src -d dist
(2)@babel/core @babel/cli @babel/preset-flow 移除类型的插件
需要添加.babelrc文件配置
运行 yarn babel src -d dist
3.flow 开发工具插件
vscode 可下载 (Flow Language Support)
https://flow.org/en/docs/editors
4.类型注解
/**
* @flow
*/
function square(n:number){
return n * n
}
let num:number = 100
// num = 'string'
function foo():number{
return 100
// return 'string'
}
function fn():void{ //没有返回值类型标识
}
5.原始类型
const a:string = 'foobar'
const b:number = Infinity
const c:boolean = false
const d:null = null
const e:void = undefined
const f:symbol = Symbol() //ES6
6.结构类型
//数组
const arr1:Array<number> = [1,2,3]
const arr2:number[] = [1,2,3]
//元组
const arr3:[String,number] = ['foo',100]
//对象
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'
//函数
function flows(callback:(string,number)=>void){
callback('string',100)
}
flows(function(str,n){
//str => string
//n => number
})
7.特殊类型
const a:'foo' = 'foo'
const type:'success' | 'warning' | 'danger' = 'success'
type StringOrNumber = string | number
const b:StringOrNumber = 'string'
// ---------------------------
const gender:?number = undefined //const gender:number | null | void = undefined
1.Mixed与Any可以接受任意类型的参数
2.差异:
(1)Mixed强类型 Any弱类型
(2)Any为了兼容以前的老代码 尽量不使用
(3)Mixed声明的函数内需要明确类型
function passMixed(value:mixed){
if(typeof value === 'string'){
value.substr(1)
}
if(typeof value === 'number'){
value * value
}
}
passMixed('string')
passMixed(100)
1.JavaScript需要运行在某一个环境中
调用内置API就有对应的类型限制
const element:HTMLElement | null = document.getElementById(‘app’)
1.下载安装
yarn add typescript --dev
yarn tsc --init // 初始化配置文件
yarn tsc // 生成编译
tsc filename.ts //编译指定文件命令
2.标准库就是内置对象所对应的声明
3.yarn tsc --locale zh-CN 以中文的形式打印错误信息
4.TypeScript Object类型(原始对象的其他类型)
const foo:object = function () {} // [] // {}
const obj:{foo:number,bar:string} = {foo:123,bar:'string'}
1.const enum PostStatus{
Draft = 0,
Unpublished = 1,
Publish = 2
}
const post = {
title:'Hello TypeScript',
content:'TypeScript is a typed superset of JavaScript',
status:PostStatus.Draft //1//0
}
1.对函数的输入和输出的约束
export {} // 确保跟其它示例没有成员冲突
function func1(a:number, b?: number,...rest:number[]): string {
return 'func1'
}
func1(100,200)
1.let age = 18 //被隐式转化为number类型
// age = 'string'
let fss // let fss:any
fss = 100
fss = 'string'
2.最好给每个变量赋予指定的类型
1.辅助TypeScript 更加明确每个变量类型 不是类型转换
const num1 = res as number
const num2 = <number>res //JSX 下不能使用
1.用来约束一个对象的结构 一个对象要实现一个接口 就必须要拥有接口中所约束的所有成员
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'
})
2.可选成员 只读成员
interface Post {
title:string,
content:string,
subtitle?:string, // 可选成员
readonly summary: string // 只读成员 不可修改
}
// 动态成员
interface Cache {
[prop: string]:string
}
const cache:Cache = {}
cache.foo = 'value1'
cache.bar = 'value2'
1.描述一类具体事物的抽象特征
2.Es6以前,函数+原型 模拟实现类 ES6开始 JavaScript中有专门的class
3.TypeScript增强了class的相关语法
class Person {
public name:string
private age:number //定义为私有 只能内部访问
protected gender:boolean // 只允许内部和子类中访问
constructor(name:string,age:number){
this.name = name // this.name 需要内部声明
this.age = age
this.gender = true
}
sayHi(msg:string):void{
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',13)
// console.log(tom.age)
// console.log(tom.gender)
const jack = Student.create('jack',18)
export {} // 确保跟其它示例没有成员冲突
interface Eat {
eat (food: string): void
}
interface Run {
run (distance:number): void
}
class Persons 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}`)
}
}
1.abstract定义后 只能被继承 不能new实例化对象了
2.父级有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('ss')
d.run(100)
1.在定义时 把不能明确的 当成一个参数传递
function CreateArray<T>(length:number,value:T):T[] {
const arr = Array<T>(length).fill(value)
return arr
}
const res = CreateArray<string>(3,'foo')