Appearance
TS
TS是JS的超集,所以JS基础的类型都包含在内
安装
npm install typescript -g
// 运行
tsc <filename>直接执行ts文件
npm i @types/node -D
npm i ts-node -g使用
基础类型
js
// 字符串
let str:string = '123'
let str1:string = `web ${str}`
console.log(str1)
// number
// const num:number = 123
// const num:number = NaN
// const num:number = Infinity
const num:number = 0x342344
// 布尔
// const b:boolean = false
const b:Boolean = new Boolean(1)
// 空值
let u:void = undefined
let n:void = null
// 函数没有返回值可以设置为void类型
function fnVoid ():void {
console.log(123)
// 返回空或者不写
return
}
fnVoid()
// null undefined
let nl:null = null
let uf:undefined = undefined
// void 类型不可以赋值给其他类型
// let v:void = undefined
// let str2:string = 'str'
// str2 = v任意类型
js
// any 可以赋值任意类型
let anys:any = '我叫小曼'
anys = 18
anys = true
// unknown
let unknow:unknown = {a: 123}
// 获取不到.a属性和方法, unknown比any更安全
// console.log(unknow.a)
// unknown类型只能赋给自身和any类型,只能当父类型使用
// let str:unknown = '123'
// let str1:string = '234'
// str1 = str接口和对象类型
js
// 接口和对象类型
// 接口定义对象
// 定义接口, 如果定义接口名相同,会合并处理
interface A {
name: String
}
interface A {
age: Number,
// 可选操作符,属性可有可无
gender?: string,
// 对象中可能存在任意的其他属性
[propName: string]: any,
// 只读属性
readonly readonlyProp: string,
// 定义函数
cb(): number
}
// 接口继承
interface B extends A {
b: string
}
// let b:B = {
// b: 'ddd'
// }
// 声明对象
let obj:A = {
name: '章三',
age: 18,
abc: 333,
readonlyProp: '1223',
cb: () => {
return 123
}
}
// 只读属性,无法重新赋值
// obj.readonlyProp = '123'
console.log(obj.readonlyProp)数组类型
js
// 数组类型
let arr:string[] = ['1','2','3']
let arr1:number[] = [1,2,3,]
let arr2:boolean[] = [true, false]
let arr3:any[] = [true, 1, '2']
// 通过泛型定义数组
let arr4:Array<number> = [1,2,3]
let arr5:Array<string> = ['1','2','3']
let arr6:Array<boolean> = [true, false]
// 二维数组定义
let arr7:number[][] = [[1,2,3],[4,5,6],[7,8,9]]
// 泛型
let arr8:Array<Array<number>> = [[1,2,3],[4,5,6],[7,8,9]]
//其中 IArguments 是 TypeScript 中定义好了的类型,它实际上就是:
// interface IArguments {
// [index: number]: any;
// length: number;
// callee: Function;
// }
function Arr(...args: any): void {
console.log(args)
let arr:IArguments = arguments
}
Arr(4,5,6)
interface ArrNumber {
[index: number]: number
}
let arr9: ArrNumber = [1, 2, 3]函数
js
// 函数扩展
// const fn = function(name: string, age?: number):string {
// return name + age
// }
// let a = fn('张三')
interface User {
name: string,
age: number
}
const fn = function(user: User): User {
return user
}
let a = fn({
name: '张三',
age: 18
})
console.log(a)
// 函数重载: 重载是方法名字相同,而参数不同,返回类型可以相同也可以不同。如果参数类型相同,则操作函数参数类型应设置为any。参数数量不同你可以将不同的参数设置为可选
function fn1(params: number): void
function fn1(params: string, params2: number): void
function fn1(params: any, params2?: any): void {
console.log(params)
console.log(params2)
}
fn1('1',2)类型断言|联合类型 | 交叉类型
js
// 类型断言|联合类型 | 交叉类型
let phone: number | string = 131223334
// 联合类型
let fn = function (type: number | boolean): boolean {
return !!type
}
// 交叉类型
interface People {
name: string,
age: number
}
interface Man {
sex: number
}
const xiaoman = (man: People & Man):void => {
// console.log(man)
}
xiaoman({
name: '小满',
age: 99,
sex: 1
})
// 类型断言
let fn1 = function(num: number | string):void {
console.log((num as string).length)
}
fn1('123')
interface A {
run: string
}
interface B {
build: string
}
let fn2 = (type: A | B): void => {
console.log((<A>type).run)
}
fn2({
build: '123'
})
const fn3 = (type: any): boolean => {
return type as boolean
}
console.log(fn3(1))内置对象
js
// 内置对象
const regexp: RegExp = /\w\d\s/
const date: Date = new Date()
const date1: number = new Date().getTime()
const error: Error = new Error('dddd')
// DOM、BOM
// const list:NodeList = document.querySelectorAll('#list li')
// const body: HTMLElement = document.body
// const div:HTMLDivElement = document.querySelector('div')
// document.body.addEventListener('click', (e: MouseEvent) => {
// console.log(e)
// })
function promise(): Promise<number> {
return new Promise<number>((resolve, reject) => {
resolve(1)
})
}
promise().then(res => {
console.log(res)
})
//dom元素的映射表
// interface HTMLElementTagNameMap {
// "a": HTMLAnchorElement;
// "abbr": HTMLElement;
// "address": HTMLElement;
// "applet": HTMLAppletElement;
// "area": HTMLAreaElement;
// "article": HTMLElement;
// "aside": HTMLElement;
// "audio": HTMLAudioElement;
// "b": HTMLElement;
// "base": HTMLBaseElement;
// "bdi": HTMLElement;
// "bdo": HTMLElement;
// "blockquote": HTMLQuoteElement;
// "body": HTMLBodyElement;
// "br": HTMLBRElement;
// "button": HTMLButtonElement;
// "canvas": HTMLCanvasElement;
// "caption": HTMLTableCaptionElement;
// "cite": HTMLElement;
// "code": HTMLElement;
// "col": HTMLTableColElement;
// "colgroup": HTMLTableColElement;
// "data": HTMLDataElement;
// "datalist": HTMLDataListElement;
// "dd": HTMLElement;
// "del": HTMLModElement;
// "details": HTMLDetailsElement;
// "dfn": HTMLElement;
// "dialog": HTMLDialogElement;
// "dir": HTMLDirectoryElement;
// "div": HTMLDivElement;
// "dl": HTMLDListElement;
// "dt": HTMLElement;
// "em": HTMLElement;
// "embed": HTMLEmbedElement;
// "fieldset": HTMLFieldSetElement;
// "figcaption": HTMLElement;
// "figure": HTMLElement;
// "font": HTMLFontElement;
// "footer": HTMLElement;
// "form": HTMLFormElement;
// "frame": HTMLFrameElement;
// "frameset": HTMLFrameSetElement;
// "h1": HTMLHeadingElement;
// "h2": HTMLHeadingElement;
// "h3": HTMLHeadingElement;
// "h4": HTMLHeadingElement;
// "h5": HTMLHeadingElement;
// "h6": HTMLHeadingElement;
// "head": HTMLHeadElement;
// "header": HTMLElement;
// "hgroup": HTMLElement;
// "hr": HTMLHRElement;
// "html": HTMLHtmlElement;
// "i": HTMLElement;
// "iframe": HTMLIFrameElement;
// "img": HTMLImageElement;
// "input": HTMLInputElement;
// "ins": HTMLModElement;
// "kbd": HTMLElement;
// "label": HTMLLabelElement;
// "legend": HTMLLegendElement;
// "li": HTMLLIElement;
// "link": HTMLLinkElement;
// "main": HTMLElement;
// "map": HTMLMapElement;
// "mark": HTMLElement;
// "marquee": HTMLMarqueeElement;
// "menu": HTMLMenuElement;
// "meta": HTMLMetaElement;
// "meter": HTMLMeterElement;
// "nav": HTMLElement;
// "noscript": HTMLElement;
// "object": HTMLObjectElement;
// "ol": HTMLOListElement;
// "optgroup": HTMLOptGroupElement;
// "option": HTMLOptionElement;
// "output": HTMLOutputElement;
// "p": HTMLParagraphElement;
// "param": HTMLParamElement;
// "picture": HTMLPictureElement;
// "pre": HTMLPreElement;
// "progress": HTMLProgressElement;
// "q": HTMLQuoteElement;
// "rp": HTMLElement;
// "rt": HTMLElement;
// "ruby": HTMLElement;
// "s": HTMLElement;
// "samp": HTMLElement;
// "script": HTMLScriptElement;
// "section": HTMLElement;
// "select": HTMLSelectElement;
// "slot": HTMLSlotElement;
// "small": HTMLElement;
// "source": HTMLSourceElement;
// "span": HTMLSpanElement;
// "strong": HTMLElement;
// "style": HTMLStyleElement;
// "sub": HTMLElement;
// "summary": HTMLElement;
// "sup": HTMLElement;
// "table": HTMLTableElement;
// "tbody": HTMLTableSectionElement;
// "td": HTMLTableDataCellElement;
// "template": HTMLTemplateElement;
// "textarea": HTMLTextAreaElement;
// "tfoot": HTMLTableSectionElement;
// "th": HTMLTableHeaderCellElement;
// "thead": HTMLTableSectionElement;
// "time": HTMLTimeElement;
// "title": HTMLTitleElement;
// "tr": HTMLTableRowElement;
// "track": HTMLTrackElement;
// "u": HTMLElement;
// "ul": HTMLUListElement;
// "var": HTMLElement;
// "video": HTMLVideoElement;
// "wbr": HTMLElement;
// }Class类
js
// Class类
// 定义属性
class Person {
public name: string
private age: number
protected sub: boolean
static aaa: string = '123'
constructor(name: string, age:number, sub:boolean) {
this.name = name
this.age = age
this.sub = sub
// this.run()
Person.run()
}
static run () {
// 静态函数内部不能访问 构造函数实例的属性
return '789'
}
}
class Man extends Person {
constructor() {
super('xiaoman',22,false)
// 可以在子类中访问 protected 关键字属性
console.log(this.sub)
}
}
let p = new Person('xiaoman',22,false)
Person.aaa
Person.run()
// public 内部外部都能访问,默认值
// private 代表定义的变量私有的只能在内部访问 不能在外部访问
// protected 代表定义的变量私有的只能在内部和继承的子类中访问 不能在外部访问
// static 静态属性和静态方法
// 通过接口约束类
interface Person1 {
run(type: boolean) : boolean
}
interface H {
set(): void
}
class A {
params: string
constructor(params) {
this.params = params
}
}
class Man1 extends A implements Person1,H {
run(type: boolean): boolean {
return type
}
set() {
}
}抽象类
js
// 抽象类 不能被实例化
abstract class A {
name: string
constructor(name: string) {
this.name = name
}
setName(name: string) {
this.name = name
}
abstract getName(): string
}
// let a = new A()
class B extends A {
constructor() {
super('xiaoman')
}
getName(): string {
return this.name
}
}
let b = new B()
b.setName('xiaoming')
console.log(b.getName())元组类型
js
// 如果需要一个固定大小的不同类型值的集合,我们需要使用元组。
// 元组类型 : 数组的变种,
// 元组(Tuple)是固定数量的不同类型的元素的组合。
let arr: [string, number] = ['xiaoming', 22]
arr[0].length
// arr[1].length
// 越界元素
// arr.push(222, 'dddd', false)
// console.log(arr)
let excel:[string, string, number][] = [
['title', 'name', 111]
]
console.log(excel)枚举类型
js
// 枚举类型
// 数字枚举
// enum Color {
// red,
// green,
// blue
// }
// 增长枚举
// enum Color {
// red = 1,
// green = 5,
// blue = 6
// }
// console.log(Color.red)
// console.log(Color.green)
// console.log(Color.blue)
// 字符串枚举
// enum Color2 {
// red = 'red',
// green = 'green',
// blue = 'blue'
// }
// console.log(Color2.red)
// console.log(Color2.green)
// console.log(Color2.blue)
// 异构枚举
enum Color3 {
yes = 1,
no = 'no'
}
// 接口枚举
// interface A {
// red: Color3.yes
// }
// let obj:A = {
// red: Color3.yes
// }
// const枚举
// 编译结果不同,会编译成常量
// const enum Types {
// success,
// fail
// }
// let code:number = 0
// if (code === Types.success) {
// }
// 反向映射: 数字枚举有效
enum Types1 {
success
}
let success:number = Types1.success
let key = Types1[success]
console.log(success,key)类型推论 | 类型别名
js
// 类型推论 | 类型别名
// 默认推论为string类型,不能赋值其他类型
// let str = '123'
// str = 123
// 默认推论为any类型
let a
a = []
a = {}
a = true
// 类型别名
// type s = string | number
// let str:s = 'xiaoming'
// let num:s = 123
// let bool:s = true
// 函数式类型别名
// type cb = () => string
// let fn:cb = () => 'xiaoming'
// console.log(fn())
// 字面量类型的别名
// type T = 'off' | 'on'
// let str:T = 'ddd'never类型
js
// never类型 用来表示不应该存在的状态
// bbb被推论成never类型,不可能存在
type bbb = string & number
// function error(msg: string):never {
// throw new Error(msg)
// }
// function loop():never {
// while(true) {
// }
// }
interface A {
type: '保安'
}
interface B {
type: '草莓'
}
// interface C {
// type: 'caicai'
// }
type ALL = A | B
function type(val:ALL) {
switch(val.type) {
case '保安':
break
case '草莓':
break
default:
const check:never = val
break
}
}symbol类型
js
// symbol类型
// let s:symbol = Symbol('xiaoming')
// let s1:symbol = Symbol('xiaoming')
// let num:symbol = Symbol(123)
// console.log(s === s1)
// console.log(s,num)
// let obj = {
// [num]: 'value',
// [s]: '草莓',
// name: 'xiaoming',
// age: 18
// }
// console.log(obj[num])
// for (let key in obj) {
// // symbol类型的key不会被遍历
// console.log(key)
// }
// console.log(Object.keys(obj))
// console.log(Object.getOwnPropertyNames(obj))
// console.log(JSON.stringify(obj))
// console.log(Object.getOwnPropertySymbols(obj))
// console.log(Reflect.ownKeys(obj))
// Symbol.iterator 迭代器 和生成器 for of
let arr:Array<number> = [4,5,6]
// let it:Iterator<number> = arr[Symbol.iterator]()
// console.log(it.next())
// console.log(it.next())
// console.log(it.next())
// console.log(it.next())
let set:Set<number> = new Set([1,2,3])
type mapKeys = string | number
let map:Map<mapKeys,mapKeys> = new Map()
map.set('1','xiaoming')
map.set('2','zhangsan')
// 迭代器
// function gen(erg:any) {
// let it:Iterator<any> = erg[Symbol.iterator]()
// let next:any = {
// done: false
// }
// while(!next.done) {
// next = it.next()
// if(!next.done) {
// console.log(next.value)
// }
// }
// }
// gen(arr)
// gen(set)
// gen(map)
// 生成器
for (let item of arr) {
console.log(item)
}
// for of 和 for in的区别
// for of 是迭代器的语法糖,可以直接遍历出有序集合的值
// for in 遍历出的是key泛型 | 泛型约束 | 泛型类
js
// 泛型 | 泛型约束 | 泛型类 语法为函数名字后面跟一个<参数名> 参数名可以随便写 例如写T,当我们使用这个函数的时候把参数的类型穿进去就可以了
// 函数式泛型
function num(a:number, b: number): Array<number> {
return [a,b]
}
num(1,2)
function str(a:string, b: string): Array<string> {
return [a,b]
}
str('1','2')
// 泛型
function add<T>(a:T, b:T):Array<T> {
return [a,b]
}
add<number>(1,2)
add<string>('1', '2')
// 简写
add(1,2)
add('1', '2')
function sub<T,U> (a: T, b: U): Array<T | U> {
let arr:Array<T | U> = [a,b]
return arr
}
sub<number, boolean> (1,false)
sub(1,false)
// 泛型约束
interface Len {
length: number
}
function getLength<T extends Len> (arg: T) {
return arg.length
}
// 传入值必须有length属性
getLength('d')
// 使用keyof约束对象
function prop<T, K extends keyof T> (obj: T, key: K) {
return obj[key]
}
let o = {
a: 1,
b: 2
}
prop(o, 'a')
// prop(o, 'c')
// 泛型类
class Sub<T> {
attr:T[] = []
add(a: T): T[] {
return [a]
}
}
let s = new Sub<number>()
s.attr = [1,2,3]
s.add(123)
let s1 = new Sub<string>()
s1.attr = ['1','2','3']
s1.add('123')命名空间
Mixins混入
ts
// 对象混入
//可以使用es6的Object.assign 合并多个对象
// 此时 people 会被推断成一个交差类型 Name & Age & sex;
interface Name {
name: string
}
interface Age {
age: number
}
interface Sex {
sex: number
}
let people1: Name = { name: "小满" }
let people2: Age = { age: 20 }
let people3: Sex = { sex: 1 }
const people = Object.assign(people1,people2,people3)Partial & Pick
js
type Person = {
name: string,
age: number,
text: string
}
// Partial
// 将定义的类型的属性都变成可选属性
type p = Partial<Person>
// 源码
type Par<T> = {
[P in keyof T]: T[P]
}
// Pick
// 将定义的类型筛选需要的属性
type p1 = Pick<Person, 'age' | 'name'>
// 源码
type Pick1<T, K extends keyof T> = {
[P in K]: T[P];
};Record & Readonly
js
// Record & Readonly
type Person = {
name: string,
age: number,
text: string
}
// Readonly
type man = Readonly<Person>
// 源码
type Readonly1<T> = {
readonly [P in keyof T]: T[P];
};
// Record 同时约束对象的key 和value 的赋值
type K = 1 | 2 | 3
type B = Record<K, Person>
let obj:B = {
1: {name: '张三', age: 18, text: '哈哈'},
2: {name: '张三', age: 18, text: '哈哈'},
3: {name: '张三', age: 18, text: '哈哈'},
}
// 源码
type Record1<K extends keyof any, T> = {
[P in K]: T;
};infer
充当占位符
发布订阅模式
ts
// 发布订阅模式
interface MyEvent {
on:(name: string, fn: Function) => void,
emit:(name: string, ...args: Array<any>) => void,
off:(name: string, fn: Function) => void,
once:(name: string, fn: Function) => void,
}
interface List {
[key: string] : Array<Function>
}
class Dispatch implements MyEvent {
list: List
constructor() {
this.list = {}
}
on (name: string, fn: Function) {
const callback = this.list[name] || []
callback.push(fn)
this.list[name] = callback
// console.log(this.list)
}
emit (name: string, ...args: Array<any>) {
let eventName = this.list[name]
if(eventName) {
eventName.forEach(fn => {
fn.apply(this, args)
})
} else {
console.error(`名称错误 ${name}`)
}
}
off (name: string, fn: Function) {
let eventName = this.list[name]
if (eventName && fn) {
let index = eventName.findIndex(fns => fns === fn)
eventName.splice(index, 1)
// console.log(eventName)
} else {
console.error(`名称错误 ${name}`)
}
}
once (name: string, fn: Function) {
let de = (...args: Array<any>) => {
fn.apply(this, args)
this.off(name, de)
}
this.on(name, de)
}
}
const o = new Dispatch()
o.on('post', (...args:Array<any>) => {
console.log(1, args)
})
o.once('post', (...args:Array<any>) => {
console.log('once', args)
})
// const fn = (...args:Array<any>) => {
// console.log(2, args)
// }
// o.on('post', fn)
// o.off('post', fn)
o.emit('post', 1, false, {name: '张三'})
o.emit('post', 1, false, {name: '张三'})proxy
js
type Person = {
name: string,
age: number,
text: string
}
const proxy = (object: any, key: any) => {
return new Proxy(object, {
get (target, prop, receiver) {
console.log('==========>get', prop)
return Reflect.get(target, prop, receiver)
},
set (target, prop, value, receiver) {
console.log('==========>set', prop)
return Reflect.set(target, prop, value, receiver)
}
})
}
const logAccess = <T>(object: T, key: keyof T): T => {
return proxy(object, key)
}
let man: Person = logAccess({
name: '张三',
age: 18,
text: '生生世世'
}, 'name')
let man2 = logAccess({
name: '张三',
id: 1
}, 'id')
man.age = 30
console.log(man)