TS
npm install typescript -g
【全局安装TS】
TS常用命令
tsc -v【出现 Version 版本号 即为TS安装成功】
tsc 文件名【运行TS文件】
tsc -w【监听文件,编译出js文件,此时可以开启另一个窗口,使用 node 文件名 (该文件名为js文件)查看运行结果】
tsc -init【生成一个文件,可以修改ts的一些选项】
注:以上命令用 - 或 -- 都可以正常执行
普通类型(原始类型)
数字类型
let NaN: number = NaN;【NAN】
let num: number = 1;【数字】
let Infinity: number = Infinity;【无穷大】
let decimal: number = 2;【十进制 与数字相同】
let hex: number = 0x1111;【十六进制】
let binary: number = 0b1111;【二进制】
let octal: number = 0o111;【八进制】
字符串类型
let str: string = 'xin.liu'
布尔类型
let bool: boolean = true
空类型
let n: null = null
未定义类型
let un: undefined = undefined
空类型【了解】
常用常见场景
function Fn ():void { } 【表示该函数无返回值,若有则报错】
知识【补充】以下操作仅处于非严格模式下的状态
let v: void = null
let v: void = undefined
所有定义为null 与 undefined类型的变量之间可以相互赋值
辅助手段
由于tsc -w 监听,node xxx.js运行效率过低且麻烦,增加一些辅助手段帮我们解放双手
npm i ts-node -g 【安装后可以直接使用 ts-node 文件名(该文件名为ts后缀)】
npm init -y 【生成package.json】
npm i @types/node -D
【package.json内出现此语句即为成功(如果位置与版本号不同一般属于正常情况)】
any类型(任意类型)与unknown类型(未知类型)
【补充】类型的级别
1.any unknown
2.Object
3.Number String Boolean
4.number string boolean
5. 1 'xx' false
6.never
注意:从上到下为包含关系,即1包含2-6所有,2包含3-6所有。。。6谁也不包含
any与unknown类型的不同之处
赋值
any类型可以赋值给其他类型,也可以接受其他类型给它赋值
unknown类型可以接受其他类型赋值,只能给unknown或any类型赋值
调用
any可以读属性和调用方法
unknown不可以读属性和调用方法
unknown类型比any类型更安全,建议先用unknown类型
【补充知识】
Object的使用方式
前情回顾【在原型链中,所有的原始类型与对象类型最终指向Object】
所以在TS中Object类型意味着一切类型
let O: Object = 1
let O: Object = '1'
let O: Object = []
let O: Object = {}
let O: Object = () => {}
object的使用方式
表示除了原始类型以外的类型,仅支持引用类型
let o: object = []
let o: object = {}
let o: object = () => {}
字面量类型
let a:{} = xxx 【该方法可以支持所有类型】
但无法对变量做任何赋值的一个操作
接口和对象类型
interface 接口名 {
定义对象中的属性及类型
}
例如:interface A{
name: string
age: number
}
【如果有重名的接口,内容会重合,但如果有(重复属性且类型不一致时)会报错】
索引签名
当数据由后端返回时,我们不知道包含了哪些数据,可以使用索引签名代表其他属性
一般使用any类型包括
注意:name和age是一定要包括的,因为在A中明确定义了这两项属性
可选项
readonly【只读】
常用于函数,函数内的执行语句一般不做修改;
或者后端传入的唯一不可变更的值如:id等属性;
继承
函数定义
function形式与箭头函数形式都可以
数组类型
let arr: number[] = [1,2] 【number可替换为任意的原始类型】
泛型
let arr: Array<number> = [true,false] 【同上,<>里可以替换类型】
定义对象数组使用interface
interface X 【定义一个对象接口】
let arr: X[] = [{...},{...}...] 【对象中的数据类型需要符合对象接口中的类型】
定义二维数组
let arr: number[][] = [ [2],[2],[2] ] 【直接在后面增加一个[],三维再加】
泛型定义二维数组
let arr: Array<Array<number>> = [ [2],[2],[2] ]
多种类型数组
let arr:any[] = [ 1,'2',true,{} ]
元组类型定义
let arr: [number,string,boolean,{}] = [ 1,'2',true,{} ]
arguments【补充】
定义函数
基本定义与【接口和对象类型】下的【函数定义】一致
函数默认的参数
函数可选参数
注意:函数默认参数与函数可选参数不可以同时使用
有默认值谈不上可选,有可选谈不上默认值
函数参数为对象
函数this类型 【了解】
如图所示,添加后在第二个框内使用this时会有提示,但是目前直接使用this也会有提示
不清楚是插件的原因还是ts版本更新增加了默认行为
函数重载
联合类型
加上 | 即可让变量多一个类型
交叉类型
与extend很像,里面的属性要一个不多一个不少
类型断言
如图,str会被断言成字符串类型,即使传进来的是数字类型
主要能力是让ts不报错
主要用途是ts面对某些复杂结构中无法推断类型时,使用类型断言辅助ts进行类型控制
类型断言的其他写法:<string>str
内置对象
ECMAScript
总结:new 什么,什么就是类型
DOM
总结:单个元素
特殊的标签 -》 HTML(元素名称)Element
不特殊的标签 -》HTMLElement
兜底的类型 -》 Element
多个元素
有多个相同元素 -》NodeList
有多个元素-》NodeListOf<> 例如:NodeListOf<HTMLDivElement | HTMLElement>
BOM
Class类型
interface Options {
el: string | HTMLElement
}
interface VueCls {
options: Options
init(): void
}
interface Vnode {
tag: string
text?: string
childern?: Vnode[]
}
class Dom {
createElement(el: string) {
return document.createElement(el)
}
setText(el: HTMLElement, text: string | null) {
el.textContent = text;
}
protected renden(data: Vnode) {
let root = this.createElement(data.tag)
if (data.childern && Array.isArray(data.childern)) {
data.childern.forEach(item => {
let child = this.renden(item)
root.appendChild(child)
})
} else {
this.setText(root, data.text)
}
return root
}
}
// class 的基本用法,继承和 类型约束 implements
// class 的修饰符 readonly(只读) private(只能在内部使用) protected(只能在内部和子类中使用) public(公共使用)
// super 的原理 父类的prototype.constructor.call
class Vue extends Dom implements VueCls {
options: Options
constructor(options: Options) {
super()
this.options = options
this.init()
}
init(): void {
let data: Vnode = {
tag: 'div',
childern: [
{
tag: 'h2',
text: '我是标题'
},
{
tag: 'p',
text: '我是内容'
}
]
}
let app = typeof this.options.el === 'string' ? document.querySelector(this.options.el) : this.options.el
app.appendChild(this.renden(data))
}
}
new Vue({
el: '#app'
})
static 静态方法只能调用静态方法及属性,不可调用其他非静态的方法和属性
class Ref {
_value: any
constructor(value: any) {
this._value = value;
}
get value() {
return this._value + 'www'
}
set value(newVal) {
this._value = newVal + '_xin.liu'
}
}
const ref = new Ref('look')
ref.value = 'Vip'
console.log(ref.value);
可以通过 get set 方法做拦截效果
抽象类
abstract 定义的抽象类
abstract 定义的方法 只能描述,不能进行实现
abstract class Vue {
name: string
constructor(name?: string) {
this.name = name;
}
getName(): string {
return this.name
}
abstract init(name: string): void
}
class React extends Vue {
init(name: string) {
}
setName(name: string) {
this.name = name
}
}
const react = new React()
react.setName('xin.liu')
console.log(react.getName());
元组类型
let arr:[ number,boolean ] = [ 1,false ]
允许赋值 arr[0] = number 类型的数据
允许越界 arr.push( number | boolean ) 越界后会推断为联合类型
只读属性 let arr: readonly [ number,boolean ] = [ 1,false ]
可选属性 let arr: readonly [ x:number,y?:boolean ] = [ 1 ] 加了?后可以没有相应的属性
读取元组的属性类型或长度 type first = typeof arr['length']
其他类型
let excel:[ string,string,number ][] = [
[ 'xx','xx',1 ],
[ 'xx','xx',1 ],
[ 'xx','xx',1 ],
[ 'xx','xx',1 ]
]
枚举类型
enum Color{
red,
green,
blue
}
数字枚举
默认从0开始计数递增
如果给red赋初值为5,则从5开始递增
可以对枚举内的变量自定义数值
字符串枚举
如果是赋值的字符串,则需要全部定义初值,因为无法递增
异构枚举:非同一种类型的枚举
enum Flag{
yes = 1,
no = 'no'
}
接口枚举
enum Flag{
yes = 1,
no = 'no'
}
interface A {
red:Flag.yes
}
let obj:A = {
red: 1 (或者Flag.yes)
}
const枚举
const enum Type{
sucess,
fail
}
不使用const
js会将枚举类型定义为一个对象
使用const
js会将其定义为一个类型数据(如数据为0 js中直接定义为0)
反向映射
enum Types { success } let success: number = Types.success let key = Types[success] console.log('value:' + success, 'key:' + key);
字符串是不可以反向映射的
类型推论
let str = 'xx' 【这里ts会自己推论这是一个字符串型】
let str 【这里既没有定义类型也没有赋值,所以ts会将它推断成any类型】
类型别名
type s = string
let str:s = 'xx'
type num = 1 extends number ? 1 : 0
extends 在类型别名中代表包含的意思
左边的值会作为右边类型的子类型
从上到下的包含关系
never类型
在函数上常用于表示该函数有问题
当出现其他未实现的数据时,error会报类型错误
type A = '1' | '2' | '3'
function Fn(value: A) {
switch (value) {
case '1': console.log(value);
break
case '2': console.log(value);
break
case '3': console.log(value);
break
default:
const error: never = value;
break
}
}
Symbol
let a: symbol = Symbol(1)
let b: symbol = Symbol(1)
a !== b 【a 与 b 都是单独的地址,所以并不相等】
for Symbol
Symbol.for('1') === Symbol.for('1')
【for全局symbol有没有注册这个key,如果有直接拿来用,没有的话他就去创建一个】
let a:symbol = Symbol(1)
let b:symbol = Symbol(1)
let obj = {
name:'123',
[a]:'18',
[b]:'1'
}
console.log(obj);
// { name: '123', [Symbol(1)]: '18', [Symbol(1)]: '1' }
// for in 无法读到symbol
for(let key in obj){
console.log(key);
// name
}
console.log(Object.keys(obj));
// [ 'name' ]
console.log(Object.getOwnPropertyNames(obj));
// [ 'name' ]
console.log(Object.getOwnPropertySymbols(obj));
// [ Symbol(1), Symbol(1) ]
console.log(Reflect.ownKeys(obj));
// [ 'name', Symbol(1), Symbol(1) ]
生成器
function* gen () {
yield Promise.resolve('xx') //同步异步
yideld 'xx'
...
}
const man = gen()
consle.log( man.next() ) //{ value:'xx',done: false }
...
//{ value:'xx',done: true }
当done为true时,表示执行到底了
迭代器
set map
let set:Set<number> = new Set([1,2,1,2,3,3]) //天然去重 1 2 3
let map:Map<any,any> = new Map()
let Arr = [1,2,3]
map.set(Arr,'1')
未完待续。。。