1. 编程语言的类型 : 动态类型语言 和 静态类型语言(c\ C++ \Jave)
2. Typescript 是什么 ?
1. 是通过在JavaScrip的基础上添加了静态类型风格的类型系统
2. 对es6到es10的预发支持,兼容各种浏览器
3. 为什么要使用Typescript
优点:
- 程序容易理解 定义函数或者方法输入输出的参数类型可容易理解程序
- 效率更高 ,通过ide代码可自动补全、自动识别错误信息
- 包容性好 , 完全兼容JavaScript
缺点: - 学习成本高
- 短期增加了一些开发成本
4. 安装typescript
node版本12.5.0 ,建议 10以上, npm 版本6.9.0 ,tsc 版本3.8.3
ts-node XXX.ts 执行ts,输出结果
tsc XXX.ts 编译ts为js文件
5. Typescript数据类型
原始数据类型 string、boolean、number、undefined 、null
注意 undefined 和 null 是所有类型的子类型,可以随意赋值给其它数据类型。
let flag :boolean = true
let issure: any = 123 // 不确定数据类型用法
issure = "abc"
复杂数据类型 数组array 和元组 tuple
let arr1: number[] = [12, 2, 34]
let arr2: [number, string] = [123, 'abc']
interface接口 针对object进行约束
interface IPerson {
readonly id : number; //readonly 只读不可编辑
age ? : number, // ? IPerson age属性可有可无
name : string
}
let na : IPerson = {
id:1,
age : 2 ,
name: 'nana'
}
interface接口 针对function输入输出约束
interface ISum {
(x:number,y:number,z ?: number) :number
}
let add :ISum = (x:number,y:number,z ?:number):number => {
if( typeof z === 'number'){
return x + y + z
}else{
return x + y
}
}
add(1,2,3)
6. 类型推断 联合类型 类型断言
let num = 123; // num 此时类型被推断为 number类型,不可修改为其他类型
//联合类型 union types : 不确定一个类型的变量到底是哪个类型的时候 ,只需要用中竖线来分割两个类型,此时只能访问此联合类型的所有类型里共有的属性或方法:
let numberOrstring: number | string;
numberOrstring = 123;
numberOrstring = 'abc';
//类型断言 可以用 as 关键字,告诉typescript 编译器参数。
function getLength(input : number | string) :number {
const inp = input as string;
if(inp.length){
return inp.length
}else{
const num = input as number;
return num.toString().length
}
}
7. Class 类
在JavaScript 使用构造函数 原型链实现继承;
Es6出现Class概念,内部使用原型链机制实现 ,有了面向对象的概念;
面向对象基本术语:
- 类(class) :定义了一切事物的抽象特点
- 对象 (Object) : 类的实例,通过New生成
- 面向对象 (OOP) 三大特性:封装 、继承、多态
封装: 将数据操作细节隐藏起来,对外只暴露接口,只通过接口访问该对象。 创建一个Animal类
class Animal {
constructor(name){
this.name = name;
}
run(){
return `${this.name} is running`
}
}
const snake = new Animal('snake')
console.log(snake.run())
继承: 子类可以继承父类的特征 。通过extends继承
class Dog extends Animal{
eat(){
return `${this.name} is eatting`
}
}
const kele = new Dog('kele')
console.log(kele.run())
console.log(kele.eat())
多态: 通过继承,子类也可以拥有自己的方法。
class Cat extends Animal{
static cate = ['cateqqq'] //静态属性、方法,与实例没有太大的关系
construcor(name){
super(name) //重写构造函数需要使用super方法
}
run(){
return 'Hi,' + super.run() //调用父类方法需要使用 super关键字
}
}
const maomao = new Cat('maomao')
console.log(maomao.run())
console.log(Cat.cate )
Typescript中的class
3种访问修饰符 ,类上的属性和方法添加权限管理
- Public :修饰的属性和方法是共有的,可以在任何地方被调用到,默认使用的
class Animal {
name: string;
constructor(name) {
this.name = name;
}
run() {
return `${this.name} is running`
}
}
const snake = new Animal('snake')
console.log(snake.run())
- private : 修饰的属性和方法是私有的,子类也不可以访问和修改
class Animal {
name: string;
constructor(name) {
this.name = name;
}
private run() {
return `${this.name} is running`
}
}
const snake = new Animal('snake')
console.log(snake.run()) //报错 属性'run'为私有属性,只能在类'Animal '中访问
- Protected: 修饰的属性和方法是受保护的,子类可以访问
- readonly : 只能读 不可以写
class Animal {
readonly name: string;
constructor(name) {
this.name = name;
}
protected run() {
return `${this.name} is running`
}
}
class Cat extends Animal {
construcor(name) {
super(name) //重写构造函数需要使用super方法
}
run() {
return 'Hi,' + super.run() //调用父类方法需要使用 super关键字
}
}
const maomao = new Cat('maomao')
console.log(maomao.run())
8. 类和接口 搭档使用
interface 用于对对象的形状进行描述,描述函数的类型,对类的一部分形为进行抽象。
- 继承困境 : 一个类只能继承自另外一个类,不同类之间需要有共同的特性,使用子类调用父类的方法不太合适。
- 特性提取成接口,用一个 implements关键字来实现接口,提高面向对象的灵活性。
//特性1 :收音机
interface Radio {
switchRadio(trigger: boolean): void //void关键字代表什么也不返回
}
//特性2 :检查电池容量
interface Checkbox {
checkBoxStatus(): void
}
//特性3 : 接口之间的继承 RadioWithCheckbox 接口继承Radio ,即有开关收音机又有检查电池容量
interface RadioWithCheckbox extends Radio {
checkBoxStatus(): void
}
class Car implements Radio {
switchRadio(trigger: boolean) {
}
}
//可写为 class Mobile implements Radio ,Checkbox ,也可以写为 :
class Mobile implements RadioWithCheckbox {
switchRadio(trigger: boolean) {
}
checkBoxStatus() {
}
}
9. 枚举 enums
枚举: 指的是常量情况,执行程序不会改变 ,在js中用const , 取值在一定范围内的一系列常量,例 一周7天; 这种情况需要用枚举表示
//数字枚举
enum Direction {
Up, //0 Up也可手动赋值 10, 下面会自动递增 Up = 10
Down, //1
Left, //2
Right //3
}
console.log(Direction.Up) //返回0
console.log(Direction[0]) //返回Up
//字符串枚举 ,提升性能 编译代码简单
enum DirectionS {
Up = 'UP',
Down = 'DOWN',
Left = 'LEFT',
Right = 'RIGHT'
}
const value = 'UP'
if (value === DirectionS.Up) {
console.log('go up!')
}
10. 泛型 Generics
泛型 指定义函数 接口或 类的时候不予先指定具体类型,而是在使用的时候在指定类型的一种特征
//泛型定义进阶1
function echo(arg) {
return arg
}
const result = echo(123) //发现返回结果为any类型,变量丧失了类型
//泛型定义进阶2
function echo1(arg: number): number {
return arg
}
const result1 = echo1(123) // echo1返回number类型,但需求有可能传入各种类型,满足不了需求
//泛型定义进阶3
function echo2(arg: any): any {
return arg
}
const result2: string = echo2(123) //丧失类型,返回any类型,还存在一个问题,传入和返回的值无法做到统一,返回any类型,传入的string类型 属于any下的类型
//泛型使用generics 占位符传入1个参数
function echo3<T>(arg: T): T {
return arg
}
const result3 = echo3(123) //传入数字123,通过类型推断,返回数字类型
//泛型使用generics 占位符传入元组
function swap<T, U>(tuple: [T, U]): [T, U] {
return (tuple[0], tuple[1])
}
const result4 = swap(['string', 123])
约束泛型
// 泛型约束进阶1
function echoWithArr<T>(arg: T): T {
console.log(arg.length) //报错,类型T上不存在length属性,所以得对泛型做约束
return arg;
}
//泛型约束进阶2
function echoWithArr1<T>(arg: T[]): T[] {
console.log(arg.length)
return arg;
}
const arrs = echoWithArr1([1, 2, 3]) //返回正确的number数组,处理并不完美, string和对象都可能有length属性
// const str = echoWithArr1('str') //返回报错,string类型参数不能赋值给元组[]类型
//进行约束,只允许这个函数传入包含length属性的变量,新建一个interface ,包含length属性
interface Iwithlength {
length: number
}
//使用extends关键字约束传入的泛型,只返回传入的参数有length属性
function echoWithLength<T extends Iwithlength>(arg: T): T {
console.log(arg.length)
return arg
}
const str1 = echoWithLength('str')
const obj1 = echoWithLength({ length: 10 })
const arrs2 = echoWithLength([1, 2, 3, 4])
const num = echoWithLength(10) //错误,类型number的参数不能赋值给Iwithlength的参数
类泛型约束
// 类泛型进阶1
class Queue {
private data = [];
push(item) {
return this.data.push(item)
}
pop() {
return this.data.shift()
}
}
const queue = new Queue()
queue.push(1)
queue.push('str')
console.log(queue.pop().toFixed()) //删除第一个元素并返回1 ,数字1可以使用toFixed方法
console.log(queue.pop().toFixed()) //ts不报错,但是编译js后会报错, string类型不可以使用toFixed方法
//类泛型约束 解决上诉问题 ,无论什么类型被推入队列 , 推出的类型和推入类型一致
class Queue1<T>{
private data = [];
push(item: T) {
return this.data.push(item)
}
pop(): T {
return this.data.shift()
}
}
const queue1 = new Queue1<number>()
queue1.push(1)
queue1.push('sre') //报错类型string的参数不能赋值给类型number的参数
console.log(queue1.pop().toFixed())
泛型在interface的应用
interface Keypair<T, U> {
key: T
value: U
} //key,value 的值动态传入
let kp1: Keypair<number, string> = { key: 1, value: 'str' }
let kp2: Keypair<string, number> = { key: 'str', value: 1 }
let kp3: Keypair<string, number> = { key: 1, value: 2 } //报错 不能将key的类型number传入 string类型
泛型表示number数组类型
let arr1: number[] = [12, 2, 34]
let arr2: Array<number> = [1, 2, 3]
11.类型别名、字面量 、交叉类型
- 类型别名type-aliase
let sum: (x: number, y: number) => number
const result = sum(1, 2)
//每次写入繁杂,可使用type关键字创建类型别名
type PlusType = (x: number, y: number) => number
let sum2: PlusType
const result2 = sum2(2, 3)
//也可使用type创建联合类型
type StrOrNum = string | number
let result3: StrOrNum = 'abc'
result3 = 124
- 字符串 字面量 ,可以提供非常方便的一系列常量写法
const str: 'name' = 'name'
const number: 2 = 2
type Directions = 'Up' | 'Down' | 'Left' | 'Right'
let toWhere: Directions = 'Left'
- 交叉类型
interface IName {
name: string
}
type IPerson = IName & { age: number }
let person: IPerson = { name: 'a', age: 27 }
12.声明文件
使用第三方库的时候,第三方库不是通过typescript写的 ,直接使用jQuery('#foo')报错,需要通过declare var 声明
declare var jQuery: (selector:string) = > any ;
//声明语句,仅仅全局定义jquery的类型,编译时的检查,最简单的声明文件写法
jquery.d.ts //声明语句放到声明文件中
使用第三库的typescript社区 :,可直接安装它的类型文件
[社区地址] (https://www.typescriptlang.org/dt/search?search=)
13.内置类型
在ts中可以随意使用最新的JavaScript语法
- 默认内置类型
//global objects
const arr: Array<number> = [12, 23, 3]
const date = new Date()
date.getTime()
const reg = /abc/
reg.test('as')
Math.pow(1, 2)
//Dom and Bom
let body = document.body;
let allLis = document.querySelectorAll('li')
allLis.length
document.addEventListener('click', (e) => {
e.preventDefault()
})
- typescript 提供内置类型
具体文档 https://www.typescriptlang.org/docs/handbook/utility-types.html ,例子:
//Partial 把传入的类型可变成可选
interface Iperson {
name: string
age: number
}
let viking: Iperson = { name: 'na', age: 12 }
type Ipartial = Partial<Iperson> // Iperson的参数都变为可选参数
let viking2: Ipartial = {}
// Omit 可以忽略传入的某个属性
type Iomit = Omit<Iperson, 'name'> //忽略name属性
let viking3: Ipartial = { age: 12 }
网友评论