基础类型(TS -- 1)
我认为这个TypeScript跟C语言是很像的,对语言的定义都有严格的规范。
let str:string = "这是字符串类型" //上方我们将str这个变量定义为了string类型,如果对他输入其他类型的内容就会报错,例如: let str:string = 666 //这个就会报错了,会提示你不能将类型"number"分配给类型"string" let muban:string = `web${str}` //我们也可以使用ES6中的模板字符串 let u:void = undefined let u:void = null //空值类型能够有这两种内容。void的内容也是不能去赋值给别人的 //某种程度上来说,void 类型像是与 any 类型相反,它表示没有任何类型。 当一个函数没有返回值时,你通常会见到其返回值类型是 void function fnvoid():void{ return//函数也可以定义为空值,如果定义了void则不能返回内容 } //undefined跟null类型的也可以交换着用的,具体区别放在了下面
八种内置类型
let str: string = "jimmy"; let num: number = 24; let bool: boolean = false;//这里接收的是布尔值,不是布尔值对象(let b:boolean = new Boolean()) let u: undefined = undefined; let n: null = null; let obj: object = {x: 1}; let big: bigint = 100n; let sym: symbol = Symbol("me");
注意点
null 和 undefined
默认情况下 null
和 undefined
是所有类型的子类型。 就是说你可以把 null
和 undefined
赋值给其他类型。
// null和undefined赋值给string let str:string = "666"; str = null str= undefined // null和undefined赋值给number let num:number = 666; num = null num= undefined // null和undefined赋值给object let obj:object ={}; obj = null obj= undefined // null和undefined赋值给Symbol let sym: symbol = Symbol("me"); sym = null sym= undefined // null和undefined赋值给boolean let isDone: boolean = false; isDone = null isDone= undefined // null和undefined赋值给bigint let big: bigint = 100n; big = null big= undefined
如果你在 tsconfig.json 指定了 "strictNullChecks":true
,null
和 undefined
只能赋值给 void
和它们各自的类型。
number 和 bigint
虽然 number
和 bigint
都表示数字,但是这两个类型不兼容。
let big: bigint = 100n; let num: number = 6; big = num; num = big;
会抛出一个类型不兼容的 ts (2322) 错误。
任意类型(TS -- 2)
npm install @types/node -D npm install ts-node -g(装全局的)
类型(任意值) -- any
let anys:any = "小满穿黑丝" anys = [] anys = 18 anys = {} anys = Symbol('666') //any类型就跟原生的是一样的,能够给任意的类型进行定义,所以在在 TypeScript 中,任何类型都可以被归为 any 类型。这让 any 类型成为了类型系统的 顶级类型 (也被称作 全局超级类型 )。
作用的地方:
- 有时候,我们会想要为那些在编程阶段还不清楚类型的变量指定一个类型。 这些值可能来自于动态的内容,比如来自用户输入或第三方代码库。 这种情况下,我们不希望类型检查器对这些值进行检查而是直接让它们通过编译阶段的检查。 那么我们可以使用
any
类型来标记这些变量 - 在对现有代码进行改写的时候,
any
类型是十分有用的,它允许你在编译时可选择地包含或移除类型检查。 你可能认为Object
有相似的作用,就像它在其它语言中那样。 但是Object
类型的变量只是允许你给它赋任意值 - 但是却不能够在它上面调用任意的方法,即便它真的有这些方法 - 当你只知道一部分数据的类型时,
any
类型也是有用的。 比如,你有一个数组,它包含了不同的类型的数据
unknown类型
unknow类型比any类型更安全
就像所有类型都可以被归为 any
,所有类型也都可以被归为 unknown
。这使得 unknown
成为 TypeScript 类型系统的另一种顶级类型(另一种的any
let unknow:unknown = {a:():number =>123} unknow.a()//报错 //unkonwn类型是不能够去调用属性跟函数的,它是 any 类型对应的安全类型
接口和对象类型(TS -- 3)
在 typescript 中,我们定义对象的方式要用关键字 interface(接口),小满的理解是使用 interface 来定义一种约束,让数据的结构满足约束的格式。
我的理解是interface是一个国企部门只招一个人的话,他们会针对走后门的那个人量身定制招聘要求,到面试的时候,这些条件少一个都不行,多了也不行,毕竟已经内定了,再叼、这些条件不仅满足了而且还会更多的技能也没用,别人就是不要你。(留下心酸的眼泪)
interface类型
interface A{ readonly name:string//这个readonly是只读属性,意思就是说只能读取,不能将其他值赋值给他 age?:number//这个问号就是可选的意思,条件稍微宽松了一些,下面引用这个age的话有没有这个属性都可以,不会报错 } let obj:A = { name = "小满嗷嗷叫"//这里如果不写name就会报错,因为我们在上面定义了A类型集合,并且在这个变量中引入了(里面必须要有name属性且类型为字符串) age = 18 }
注意:这个规定的属性不能多也不能少,参考我上面的案例
可选属性 -- ?
操作符
interface A{ readonly name:string age?:number//这个问号就是可选的意思,条件稍微宽松了一些,下面引用这个age的话有没有这个属性都可以,不会报错 } let obj:A = { name = "小满嗷嗷叫" age = 18//age写不写无所谓 }
任意属性 -- [propName:string]
需要注意的是,一旦定义了任意属性,那么确定属性和可选属性的类型都必须是它的类型的子集
interface Person{ name:string, age?:number, [propName:stirng]:string|number//这个属性一旦定义了,引用这个Person的对象就能够写入任意属性,属性的形式主要看冒号后面你定义了什么类型,比如在这里定义的类型就是string和number类型,不是这两者的类型就会报错,包括在Person里面定义除了string跟number之外其他类型也会报错 //可以理解为这个 [propName:stirng]任意属性的优先度相当高 注意string与number中间的 `|` 符号,小飞棍来咯,这是联合类型,后面笔记会写,这里就当作将string和number类型关系到了一块,有点像逻辑或,满足联合起来的其中一个条件都行,两个也可以 }
只读属性 -- readonly
只读属性必须在声明时或构造函数里被初始化。
interface A{ readonly name:string//这个readonly是只读属性,意思就是说只能读取,不能将其他值赋值给他 } let obj:A = { name = "小满嗷嗷叫" } obj.name = "小满芳龄18"//报错 console.log(obj)//能够读取 let name1 = obj.name console.log(name1)
继承属性 -- extends
儿子在前面,父亲在后面。也就是说顺序是 儿子 继承于 父亲
父亲的部分会继承给儿子,父亲的部分如果没有使用?操作符的话,引用儿子的 对象 是必须将父亲的部分都写下去。一说到这个就想到现在有的地方买房子,出政策能够绑定3代人一起还款,父债子还,跑不掉的,连债务都继承了还不能摆脱,这政策太鸡儿黑心了,绝户计
interface A{ name:string } interface B extends A{ age:number } let p:B{ name:"有看到小满的裤子吗?" age:88//两种类型都要写 }
数组类型(TS -- 4)
普通的声明方式
//类型加中括号 let arr:number[] = [123] //这样会报错定义了数字类型出现字符串是不允许的 let arr:number[] = [1,2,3,'1'] //操作方法添加也是不允许的 let arr:number[] = [1,2,3,] let arr:number[] = [1,2,3,4];//数字类型的数组 let arr2:string[] = ["1","2","3","4"];//字符串类型的数组 let arr3:any[] = [1,"2",true,undefined,[],{}];//任意类型的数组 let arr4:number[][][] = [[[]],[[]],[[]]] //这个也能够决定你二维数组还是三维数组想要套几层就写几层
泛型 -- Array <类型>
规则 Array <类型> let arr1:Array<number> = [1,2,3,4,5] let arr2:Array<string> = ["1,2,3,4,5"] let arr3:Array<boolean> = [true] //泛型数组套娃写法(还能够决定数组里面数组的类型之类的) let arr4:Array<Array<number>> = [[123],[456]]
类数组 -- arguments
是所有参数的一个集合
function Arr(...args:any):void{//...args为ES6的解构方式,任意类型,不能有返回值 console.log(arguments)//输出{'0':4,'1':56,'2':789} let arr:number[] = arguments//会报错,报缺少类型number[]的以下属性:pop,push,concat,join let arr:IArguments = arguments//解决方法 //其中 IArguments 是 TypeScript 中定义好了的类型,它实际上就是: interface IArguments { [index: number]: any; length: number; callee: Function; } Arr(4,56,789)
接口表示数组
一般用来描述类数组
interface ArrNumber { [index: number]: number;//后面的才是定义类型的 //[index: number]: string;这个就是定义字符串的了 } let Arr: ArrNumber = [1, 2, 3, 4, 5]; //let Arr: ArrNumber = ["1, 2, 3, 4, 5"]; //表示:只要索引的类型是数字时,那么值的类型必须是数字。
函数扩展(TS -- 5)
函数内参数类型也是可以定义的
const fn(name:string,age:number):string{ return name + age } let a = fn('小满',10000)//输入不符合上述参数内定义的类型就会出错 console.log(a)//输出小满10000 -------------------------------------------------------------------- const fn(name:string,age:number = 666):string{//如果在下面使用的时候,没有参数传进来就会以你在这里设置的默认参数执行,比如这个666 return name + age } let a = fn('小满')//输入不符合上述参数内定义的类型就会出错 console.log(a)//输出小满666 -------------------------------------------------------------------- const fn(name:string,age?:number = 666):string{//也可以使用这个`?`操作符,age传不传就变成可选的了 return name + age } let a = fn('小满穿女仆装')//输入不符合上述参数内定义的类型就会出错 console.log(a)//输出小满穿女仆装
对象形式的定义
跟定义对象差不多,但是在针对多个参数的时候会更加的方便,且记得引用的时候要写成({xxxx})形式,不然会报错,输出的是数组形式的
interface User{ name:string; age:number } const fn(user:User):User{//这里的参数填写方式就变得简单了 return user } let a = fn({ name:"'小满", age:18 })//输入不符合上述参数内定义的类型就会出错 console.log(a)//输出{name:'小满',age:18}
函数重载
重载是方法名字相同,而参数不同,返回类型可以相同也可以不同。
如果参数类型不同,则参数类型应设置为 any。
参数数量不同你可以将不同的参数设置为可选。
为了让编译器能够选择正确的检查类型,它与 JavaScript 里的处理流程相似。 它查找重载列表,尝试使用第一个重载定义。 如果匹配的话就使用这个。 因此,在定义重载的时候,一定要把最精确的定义放在最前面。
function fn(params:number):void//第一套规则 function fn(params:string,params2:number):void//第二套规则 function fn(params:any,params?:any):void{ console.log(params) console.log(params2) } let a = fn(1,1) //输出1跟undefined,因为遵循的是第一套规则 let a = fn("1",1) //输出"1"跟1,遵循的是第二套规则
联合类型|类型断言|交叉类型(TS -- 6)
联合类型
联合类型能够让我们可选我们自己需要的类型部分,如果需要的类型超过或者达到2个,那就可以使用。
那为什么不使用any呢?那是因为我们需要的并不是所有类型都能通过,我只希望这两个或者3个类型能够通过,如果需要的类型超过或着达到两个都使用any的话,那就和JavaScript原生没有区别了
//例如我们的手机号通常是13XXXXXXX 为数字类型 这时候产品说需要支持座机 //所以我们就可以使用联合类型支持座机字符串 let myPhone: number | string = '010-820' //这样写是会报错的应为我们的联合类型只有数字和字符串并没有布尔值 let myPhone: number | string = true//报错
函数使用联合类型
这个!!是怎么回事呢?
我们知道一串数字想变成字符串只要加上""就能隐式转换成字符串。
那一个类型只要!
就能进行反转,!只有正反,也就是false跟true,这种就有点类似隐式转换了,我们连续转两次就相当于当前形式的布尔值类型了
let fn = function(type:number):boolean { return !!type//将type强行转化为布尔值类型,如果没用进行转化的话是会报错的 } -------------------------------------------------------------------- let fn = function(type:number|boolean):boolean { return !!type//将type强行转化为布尔值类型,如果没用进行转化的话是会报错的 } let result = fn(1) console.log(result);//true
交叉类型
多种类型的集合,联合对象将具有所联合类型的所有成员
interface Pople{ name:string age:number } interface Man{ sex:number } const xiaoman = (man:Pople & Man):void => {//这里通过了&将Pople跟Man交叉在了一起,则man需要处理Pople也要处理Man。还可以继续跟更多个interface console.log(man) } xiaoman({ name:"小满今天坏掉了" age:18 sex:1//如果sex不写是会报错的,会提示你少写了一个sex })
类型断言
语法格式,值 as 类型 或者 <类型>值
需要注意的是,类型断言只能够「欺骗」TypeScript 编译器,无法避免运行时的错误,反而滥用类型断言可能会导致运行时错误
覆盖它的推断,并且能以你任何你想要的方式分析它,这种机制被称为「类型断言」。TypeScript 类型断言用来告诉编译器你比它更了解这个类型,并且它不应该再发出错误
当 S
类型是 T
类型的子集,或者 T
类型是 S
类型的子集时,S
能被成功断言成 T
。这是为了在进行类型断言时提供额外的安全性,完全毫无根据的断言是危险的,如果你想这么做,你可以使用 any
。
2、类型断言的用途
(1)将一个联合类型推断为其中一个类型
(2)将一个父类断言为更加具体的子类
(3)将任何一个类型断言为 any
(4)将 any 断言为一个具体的类型
原型:
let fn = function(num:number | string):void{ console.log(num.length);//这里会报错,因为我们确实没有.length这个内容 } fn("12345") -------------------------------------------------------- 断言写法 let fn = function(num:number | string):void{ console.log((num as string).length);//用括号括起来,as断言他是string类型 } fn("12345")//这样会打印出5 fn(12345)//这样会打印出undefined 另一个例子 interface A{ run:string } interface B{ build:string } let fn(type:A | B) =>{ console.log((<A>type).run); } fn({ build:"123"//这里是没办法传过去的,断言是不能够滥用的,因为我们确实没有.run这个内容 })
临时断言
1.使用any临时断言
window.abc = 123 //这样写会报错因为window没有abc这个东西 (window as any).abc = 123 //可以使用any临时断言在 any 类型的变量上,访问任何属性都是允许的。 在下面的例子中,将 something 断言为 boolean 虽然可以通过编译,但是并没有什么用 并不会影响结果,因为编译过程中会删除类型断言 function toBoolean(something: any): boolean { return something as boolean; } let bbb = toBoolean(1); console.log(bbb) // 返回值为 1 //
as const
是对字面值的断言,与 const 直接定义常量是有区别的
如果是普通类型跟直接 const 声明是一样的
内置对象(TS -- 7)
const names = '小满' names = 'aa' //无法修改 let names2 = '小满' as const names2 = 'aa' //无法修改 // 数组 let a1 = [10, 20] as const; const a2 = [10, 20]; a1.unshift(30); // 错误,此时已经断言字面量为[10, 20],数据无法做任何修改 a2.unshift(30); // 通过,没有修改指针。之所以没有修改指针是因为const的性质是决定了指针指向的位置是已经固定不会发生改变的了,这个30想要添加进去除非直接修改存储值的地方
ECMAScript的内置对象
JavaScript 中有很多内置对象,它们可以直接在 TypeScript
中当做定义好了的类型。
Boolean
、Number、string
、RegExp
、Date
、Error
const regexp:Regexp = /\w\d\s///声明正则 const date:Date = new Date()//对象类型 //const date:Date = new Date().getTime() number类型 const error:Error('错误')
总结
let b: Boolean = new Boolean(1) console.log(b) let n: Number = new Number(true) console.log(n) let s: String = new String('小满今天穿白丝') console.log(s) let d: Date = new Date() console.log(d) let r: RegExp = /^1/ console.log(r) let e: Error = new Error("error!") console.log(e)
DOM 和 BOM 的内置对象
Document
、HTMLElement
、Event
、NodeList
等
const list:NodeList = document.querySelectorAll('#list li') console.log(list) //NodeList 实例对象是一个类似数组的对象,它的成员是节点对象。Node.childNodes、document.querySelectorAll () 返回的都是 NodeList 实例对象。 [1] NodeList 对象代表一个有序的节点列表。 const body:HTMLElement = document.body console.log(body) const div:HTMLDivElement = document.querySelector('div') console.log(div) document.body.addEventListener('click',(e:MouseEvent)=>{ console.log(e) }) //promise function promise():Promise<number>{//Promise是类型,number是泛型 return new Promise<number>(resolve,rejuct)=>{ resolve(1)//如果不进行断言的话会报错 } } promise().then(res=>{ console.log(res)//返回1,这里会提示你res应该输入number类型 }) let body: HTMLElement = document.body; let allDiv: NodeList = document.querySelectorAll('div'); //读取div 这种需要类型断言 或者加个判断应为读不到返回null let div:HTMLElement = document.querySelector('div') as HTMLDivElement document.addEventListener('click', function (e: MouseEvent) { }); //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; }