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')
类型小结
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')