TypeScript 基于JavaScript之上的语言 解决了JavaScript类型系统的问题
强类型与弱类型 静态类型与动态类型 Javascript自由类型系统的问题 Flow静态类型检查方案 TypeScript语言规范与基本应用
类型系统
强类型与弱类型(类型安全) 强类型有更强的类型约束,而弱类型中几乎没有什么约束
强类型语言中不允许任意的隐式类型转换 弱类型语言则允许任意的数据隐式类型转换 静态类型与动态类型(类型检查)
静态类型: 一个变量声明时他的类型就是明确的, 声明过后, 它的类型就不允许再修改 动态类型: 运行阶段才能够明确变量的类型且变量的类型随时可以改变(动态类型中变量没有类型, 变量中存放的值是有类型的) Javascript是动态类型语言
JavaScript类型系统特征
弱类型 且 动态类型 (缺失了类型系统的可靠性) JavaScript没有编译环节
弱类型语言开发大型应用的常见问题
强类型语言的优势
错误更早的暴露(编译阶段就暴露)
代码更智能, 编码更准确
重构更牢靠
减少不必要的类型判断
Flow
JavaScript的类型检查器, 2014年Facebook推出, 弥补js弊端 类型注解: 加参数后边加一个冒号, 在跟上一个数据类型 Flow只是一个小工具
Flow编译移除注解
开发工具插件(Flow Language Support)
类型推断(Type inference)
function square ( n) {
return n * n
}
square ( '100' )
类型注解(Type Annotations)
function square ( n: number) {
return n * n
}
square ( '100' )
let num: string
num = 100
function foo ( ) : number {
return 10
return '10'
}
function foo ( ) : void {
}
原始类型(Primitive Types)
const a: string = 'string'
const b: number = Infinity
const c: boolean = true
const d: null = null
const e: void = undefined
const f: symbol = Symbol ( )
数组类型(Array Types)
const arr1: Array< number> = [ 1 , 2 , 3 , 'ee' ]
const arr2: number[ ] = [ 1 , 2 , 3 ]
const foo: [ string, number] = [ 'foo' , 100 ]
对象类型(Object Types)
const obj1: { foo: string, bar: number} = { foo: 'string' , bar: 100 }
const obj2: { foo? : string, bar: number} = { bar: 100 }
const obj3: { [ string] : string} = { }
obj3. key1 = 'value3'
obj3. key2 = 100
任意类型(Any Types)
function passMaxid ( value: mixed) {
if ( typeof value === 'string' ) {
value. substr ( 1 )
}
if ( typeof value === 'number' ) {
value * value
}
}
passMaxid ( 'str' )
passMaxid ( 100 )
function passAny ( value: any) {
value. substr ( 1 )
value * value
}
passAny ( 'str' )
passAny ( 100 )
函数类型(Function Types)
function foo ( callback: ( string, number) => void ) {
callback ( 'foo string' , 100 )
}
foo ( function ( str, num) {
} )
特殊类型
const element: HTMLElement | null = document. getElementById ( 'app' )
const element2: HTMLElement | null = document. getElementById ( 100 )
const element1: ? HTMLElement = document. getElementById ( 'app' )
类型小结
https://flow.org/en/docs/types/ https://www.saltycrane.com/heat-sheets/flow-type/latest/
Flow运行环境API(内置对象)
TypeScript JavaScript的超集(superset)、扩展集
任何一种JavaScript运行环境都支持TypeScript 功能更为强大, 生态更健全、更完善(相比Flow) 前端领域的第二语言 TypeScript属于[渐进式] 缺点一: 语言本身多了很多概念 缺点二: 项目初期, TypeScript会增加一些成本
快速上手 可以完全按照 JavaScript 辨准语法编写代码
const hello = ( name: string ) => {
console. log ( `hello ${ name} ` )
}
hello ( 'TypeScript' )
hello ( 100 )
TypeScript配置文件 yarn tsc --init
TypeScript原始类型(Primitive Types)
const a: string = 'foo'
const b: number = 100
const c: boolean = true
const e: void = undefined
const f: null = null
const g: undefined = undefined
const h: symbol = Symbol ( )
TypeScript标准库声明(内置对象类型)
中文错误信息
yarn tsc --locale zh-CN (命令行显示中文错误信息) vscode编译器-setting中搜索 typescript locale选项
TS作用域问题
const a = 223
export { }
TS的Object类型(Object Types)
const foo: object = function ( ) { }
const obj: { foo: string, bar: number} = { foo: '233' , bar: 222 }
TS数组类型(Array Types)
const arr1: Array< number> = [ 2 , 3 , 4 ]
const arr2: number[ ] = [ 3 , 5 , 3 ]
function sum ( ... args: number[ ] ) {
return args. reduce ( ( prev, current) => prev + current, 0 )
}
sum ( 2 , 3 , 2 , )
TS元组类型(Tuple Types)
const tuple: [ number, string, number] = [ 1 , 'dd' , 22 ]
const [ age, name] = tuple
TS枚举类型(Enum Types)
给每一个变量一个更好的名字, 见名知意 一个枚举中只可能出现固定的几个值, 不会出现超出范围的可能性 枚举类型会入侵到运行代码
const enum PostStatus {
Draft = 6 ,
Unpublished,
Published,
}
const enum PostStatusStr {
Draft = 'aaa' ,
Unpublished = 'ddd' ,
Published = 'ggg' ,
}
const post = {
title: 'Hello TS' ,
content: 'TS is a typed superset of JavaScript.' ,
status: PostStatus. Draft
}
TS函数类型(Function Types)
function func1 ( a: number, c: number = 22 , b? : 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'
}
任意类型(Any Types)
function stringify ( value: any) {
return JSON . stringify ( value)
}
stringify ( '2000' )
stringify ( 222 )
stringify ( true )
let foo: any = 'string'
foo = 200
foo. bar ( )
隐式类型推断(Type Inference)
let age = 111
let foo
foo = 22
foo = 'string'
类型断言(Type assertions)
const nums = [ 100 , 120 , 119 , 112 ]
const res = nums. find ( i => i> 0 )
const num1 = res as number
const num2 = < number> res
const square = num1 * num1
const square2 = num2 * num2
接口(Interface)
interface Post {
title: string
content: string
subtitle? : string
readonly summary: string
}
function printPost ( post: Post) : void {
console. log ( post. title)
console. log ( post. content)
}
printPost ( {
title: 'hello ts' ,
content: 'a js superset' ,
summary: 'summary'
} )
const hello: Post = {
title: 'hello ts hello' ,
content: 'a js superset hello' ,
summary: 'summary hello'
}
interface Cache {
[ key: string] : string
}
const cache: Cache = { }
cache. foo = 'foo'
cache. bar = 'bar'
cache. baz = 'baz'
类 (Classes)
描述一类具体事物的抽象特征 Typescript增强类ES6中class的相关语法 访问修饰符 只读属性
class Person {
name: string
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 PersonSync {
public name: string
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} ` )
}
}
const tom = new PersonSync ( 'tom' , 18 )
console. log ( tom. name)
class Student extends PersonSync {
private constructor ( name: string, age: number) {
super ( name, age)
console. log ( this . gender, 'gender111' )
}
static create ( name: string, age: number) {
return new Student ( name, age)
}
}
const student = Student. create ( 'liuchao' , 10 )
class Person {
public name: string
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} ` )
}
}
const tom = new Person ( 'tom' , 18 )
console. log ( tom. name)
export { }
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 a = new Dog ( )
a. eat ( 'apple' )
a. run ( 2000 )
类与接口
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) : void {
console. log ( `直立行走: ${ distance} ` )
}
}
class Animal implements Eat , Run {
eat ( food: string) : void {
console. log ( `呼噜噜的吃: ${ food} ` )
}
run ( distance: number) : void {
console. log ( `爬行: ${ distance} ` )
}
}
泛型(Generics)
定义函数接口或类的时候没有具体类型, 使用的时候传递具体类型
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 , 1000 )
console. log ( res)
const res1 = createArray< string> ( 4 , '200' )
console. log ( res1)
类型声明(Type Declaration)
import { camelCase } from 'lodash'
import qs from 'query-string'
qs. parse ( '?key=value&key2=value2' )
const res = camelCase ( 'hello typed' )