一. 认识TypeScript(简称TS)
TypeScript语言是Javascript语言的超集, 最终会编译成Javascirpt。
TypeScript = Javascript + 类型系统 + ES6+。
相比Flow, TS作为一门完整的编程语言,功能更强大、生态更健全。
Angular Vue.js3 都开始使用TypeScript。
TS非常适合用于大型、长期项目的开发,对于短期小项目而言,增加的开发成本得不偿失。
二. TypeScript的使用
1. TypeScript快速上手
安装:yarn add typescript --dev
安装完成后,在node_modules/.bin目录下,会看到tsc(TypeScript compiler)命令,用处是编译ts代码(默认编译到ECMAScript3) 但无法编译新版本ES的API如 Object.assign,Symbol等。
新建一个ts文件:touch 01-get-start.ts
编译该文件为js: yarn tsc 01-get-start.ts
2. TypeScript配置文件 tsconfig.json
用tsc(typescript compiler)命令编译整个ts项目/工程:
新建ts配置文件 tsconfig.json :yarn tsc --init
注意:仅用 tsc 编译指定的文件时不会应用tsconfig.json配置文件;只有直接使用 tsc (yarn tsc)编译整个工程的时候,才会用上tsconfig.json配置文件。
tsconfig.json文件中的几个常用配置项:
{
"compilerOptions": {
// 编译后的目标js的版本
"target": "ES5",
// 输出代码用什么方式进行模块化
"module": "commonjs",
// 如果开启本行设置,则会覆盖TS默认使用的标准库
"lib": ["ES2015", "DOM"],
// 编译结果的js代码输出文件夹
"sourceMap": true,
// 需要编译的源ts代码文件夹
"outDir": "tsdist",
// 开启后可在调试时使用ts源代码
"rootDir": "tssrc",
// 开启所有严格检查 (严格模式下:所有变量都需明确指定类型)
"strict": false,
}
}
3. TypeScript示例
# TS原始类型
仅在非严格模式下:
TS中允许 string number boolean 为空(null 或 undefined);
void类型里可以存放 undefined 和 null。
const a: string = 'foo' // 在非严格模式下还可以存放null或undefined
const b: number = 123
const c: boolean = true
const d: null = null
const e: undefined = undefined
const f: void = undefined // 在非严格模式下还可以存放null
# TS作用域问题
const hello: string = 'hello'
export {} // export {} 是固定语法,表示将本文件中所有变量都导出,则不同文件中同名变量就不会冲突了
# TS object类型(可用于对象、数组、函数 等所有非原始类型的数据)
const array: object = [1,2]
const person: object = {}
const fn1: object = function(){}
# TS {}类型(专指对象类型)
const obj: {} = {}
const obj2: {name: string, age: number} = {name: 'Lily', age: 18}
# TS 数组类型
const arr1: Array<number> = [2, 4]
const arr2: number[] = [2, 6] // 推荐
function sum(...args: number[]){}
# TS枚举类型
// enum 最终会编译为一个双向的键值对对象
enum Status {
Draft = 0,
Unpublished = 1,
Published = 2
}
// const enum 则仅替换代码中的枚举为值
const enum Status2 {
Draft = 0,
Unpublished = 1,
Published = 2
}
const post = {
title: 'Title',
constent: 'Ts is a typed lang.',
status: Status.Draft
}
# TS函数类型
/* 1- 函数声明定义的函数 */
function f1(a: number, b?:number): string{
return 'f1'
}
f1(1,2)
f1(2)
// 接受任意个参数
function f2(a: number, ...rest: number[]): string{
return ''
}
f2(1)
f2(1,2,3,4)
/* 2- 函数表达式 声明的函数 */
const f1 = (a: number) => string
= function(a: number){ return 'str1' }
# TS类型断言
把明确知道类型的变量的类型告知TypeScirpt:
// 假如明确知道nums的数据内容 其中必有一个大于0的
const nums = [10,20,30]
const res = nums.find(t => t > 100) // TS会推断 res 类型为 number 或 undefined
const num1 = res as number // 类型断言
const num2 = <number>res // 类型断言
# TS interface 约定对象结构
// TS interface 接口约定对象结构
interface Post {
title: string;
content: string;
subtitle?: string; // 本属性可选
readonly sumarry: stirng; // 本属性只读
}
const myPostObj: Post= {
title: 'My Title',
content: 'My Content',
summary: 'Summary'
}
function printPost(post: Post){
console.log(post.title)
console.log(post.content)
}
printPost(myPostObj)
# TS interface 约定 动态对象类型(对象的属性不确定)
interface Cache {
[prop: string]: string // string类型的键 string类型的值
}
const cache1: Cache = {}
cache1.foo = 'str1'
cache1.name = 'str2'
# TS 中类的基本使用(类的属性必须在TS中声明)
class Person {
// 声明类的属性
name: string
age: number
constructor(name, age){
this.name = name
this.age = age
}
sayHi(msg: string): void{
console.log(`I am ${this.name}, ${msg}`)
}
}
# TS 中类成员的访问修饰符(public private protected)
class Person2{
name: string = 'init name' // 属性默认是public公有属性
private age: number // private 私有属性 仅允许在该类内部访问
protected gender: boolean // protected 保护属性 仅允许在该类内部和其子类内部访问
}
# TS 中属性的只读标识 readonly
class Person2{
// readonly只读属性 可在属性声明时赋值或在构造函数内赋值(两者只能做其一)
// 赋值后类内类外都不允许修改
private readonly id: number
}
# TS 类 实现 接口
/* 类实现接口 */
interface Eat {
eat(food: string): void
}
interface Run {
run(distance: number): string
}
class Animal implements Eat, Run {
eat(food: string): void {
console.log('呼噜呼噜的吃' + food)
}
run(distance: number): string {
console.log('时速' + distance)
return '时速' + distance
}
}
const dog = new Animal()
dog.eat('肉骨头')
dog.run(100)
# TS 类 继承 抽象类
/* 类继承抽象类 */
// 抽象类 抽象类中可以包含具体方法和抽象方法
abstract class Something {
abstract makeSound(voice: string): void // 抽象方法
sayHi(name: string): void {
console.log('Hi, I am ' + name)
}
}
class Person extends Something {
name: string;
age: number;
constructor(name: string, age: number){
super()
this.name = name;
this.age = age;
}
makeSound(voice: string): void {
console.log('As man, I ' + voice)
}
}
class Car extends Something {
makeSound(voice: string): void {
console.log('As car, I ' + voice)
}
}
const lily = new Person('Lily', 16)
console.log(lily.name)
lily.makeSound('Speak')
lily.sayHi('Lily')
console.log('- - - - - - - -')
const car = new Car()
car.makeSound('Honking')
/* 输出:
Lily
As man, I Speak
Hi, I am Lily
- - - - - - - -
As car, I Honking
*/
# TS 范型
// TS 范型
function createNumberArray(length: number, value: number): number[] {
const array = Array<number>(length).fill(value)
return array
}
function createStringArray(length: number, value: string): string[] {
const array = Array<string>(length).fill(value)
return array
}
// 范型:用T代表使用时的具体类型
function createArray<T>(length: number, value: T): T[] {
const array = Array<T>(length).fill(value)
return array
}
const a1 = createNumberArray(3, 1)
console.log('a1: ', a1)
const a2 = createStringArray(3, 'a')
console.log('a2: ', a2)
const a3 = createArray<number>(3, 1)
console.log('a3: ', a3)
const a4 = createArray<string>(3, 'a')
console.log('a4: ', a4)
/* 输出
a1: [ 1, 1, 1 ]
a2: [ 'a', 'a', 'a' ]
a3: [ 1, 1, 1 ]
a4: [ 'a', 'a', 'a' ]
*/
# TS 手动类型声明
import { camelCase } from 'lodash'
// 如果某个第三方模块的方法 没有类型声明
// 则可以手动为其添加一个类型声明
// 通常可以查看模块引入处的提示 安装其对应的类型声明 @types/xxx .d.ts文件
declare function camelCase(input: string): string
const res = camelCase('hello typed')
console.log(res)
本文 完。