TypeScript 学习笔记 TypeScript 的类型校验是给程序员看的,在编译后不会存在TS代码。
类型注解 1 2 3 4 5 6 function fn (person : string ):void { } fn ('str' ) const test :number = 1
有哪些基础类型注解? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 :string :number :boolean :null :undefined :symbol :object :any :void :never
什么是类型注解和类型推断、类型断言? 类型注解 是显式的标注类型
类型推断 是编辑器根据值来自动推断出类型 (编辑器中鼠标移到变量会显示类型的提示)。
类型断言 是告诉编译器,“相信我,它就是这个类型”。
1 2 3 4 5 6 7 8 9 const myNumber : number = 123 const myString = 'test' const someValue :any = 'abc' const strLength :number = (someValue as string ).length
类型断言 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 const el = document .querySelector ('#img' );(el as HTMLImageElement ).src = 'xx' type TestObj = { a : string }; const obj = { test : <TestObj >{ a : 'aaa' } } const obj = { test : { a : 'aaa' } as TestObj , }
对象的类型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 const xiaojiejie : { name : string , age : number } = { name : '小红' , age : 18 } const obj :object = {}interface Person { name : string age : number } const xjj : Person = { name : 'xh' , age : 18 } class Parson { }const xiaobai : Parson = new Parson ()const fn : ()=> string = () => '123'
函数的类型注解 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 function getTotal2 (one : number , two : number ): number { return one + two } getTotal2 (1 ,2 )function sayHello ( ): void { console .log ("Hello" ) } function setTimer ( ):never { throw new Error () console .log (123 ) } function add ({ one, two }: {one: number , two: number } ) { return one + two } const total = add ({one : 1 , two : 2 })type Callback = (a : string ) => string let fn : Callback = (a ) => '' interface ICallBack { (a : string ): string } let fn1 : ICallBack = (a ) => ''
函数中的this类型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 interface TestObj { a : number , fn : (x : number ) => void } let obj : TestObj = { a : 1 , fn (this : TestObj , x : number ){ this .a } } let obj2 : TestObj = { a : 1 , fn (this : TestObj , x : number ) { return () => { this .a } } }
函数重载 (函数参数间的组合约定) 原生js中并没有真正的函数重载,重名函数会被覆盖,但ts中可以有。
浅谈JavaScript函数重载
ts支持函数重载,一般用于针对传入不同的参数或参数数量以及返回值之间的类型约定。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function showOrHide (ele : HTMLElement , attr : 'display' , value : 'block' | 'nonde' );function showOrHide (ele : HTMLElement , attr : 'opacity' , value : number );function showOrHide (ele : HTMLElement , attr : any , value : any ) { } interface Fn { (name : string ): string (name : number ): number } const fn : Fn = () =>
更多 ts函数重载知识
数组的类型注解 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 const numberArr : number [] = [1 , 2 , 3 ]const stringArr : string [] = ['a' , 'b' ]const undefinedArr : undefined [] = [undefined , undefined ]const arr : (number | string | boolean )[] = [1 , 'a' , true , false ] type lady = { name : string , age : number }const xiaojj : lady[] = [ { name : 'xiaojj' , age : 90 }, { name : 'j' , age : 30 } ] class Ady2 { name : string ; age : number ; } const xiaojj2 : Ady2 [] = [ { name : 'xiaojj' , age : 90 }, { name : 'j' , age : 30 } ]
元组 元组,可以理解为:已知元素数量和类型的数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 const xjj :(string | number )[] = ['a' ,22 ,'b' ] const xjj1 : [string , number , number ] = ['a' , 22 , 33 ] const xjj2 : [string , number , number ][] = [ ['a' , 22 , 33 ], ['a' , 22 , 33 ] ]
接口 接口,可以理解为对象属性的类型描述。和类型别名类似,不同的是 接口必须是一个对象,而别名可以直接是一个类型,如 type Girl = string
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 interface Girl { readonly name : string ; age : number ; waistline ?: number ; [propname : string ]: any ; say (): string ; } interface Teacher extends Girl { teach (): string ; } const girl = { name : '大脚' , age : 18 , sex : '女' , say ( ) { return '欢迎光临' }, teach ( ) { return '教' } } const screenResume = ({ name, age, bust, sex }: Girl ) => { console .log (name, age, bust, sex) } const getResume = ({ name, age, bust, teach}: Teacher ) => { teach (); console .log (name, age, bust) } screenResume (girl)getResume (girl)class xiaojjj implements Girl { name = "xiaojj" age = 18 bust = 98 sex = '女' say ( ) { return '欢迎光临' } }
可索引的类型
1 2 3 4 5 6 interface Arr { [index : number ]:string } const myArr :Arr = ['1' ,'2' ,'3' ]const myStr :string = myArr[1 ]
ES6 class类中应用TS class类的修饰器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class Person { name : string private age : 18 public sayHello ( ) { console .log (this .name + this .age + 'say hello' ) } } class Teacher2 extends Person { public sayBye ( ) { console .log (this .name + ' say bye' ) } } const person = new Person ();person.name = 'test' console .log (person.name )
class类的构造函数中使用类型校验 1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Person2 { constructor (public name : string ) { this .name = name } } class Teacher3 extends Person2 { constructor (public age : number ) { super ('test-name' ) } } const teacher3 = new Teacher3 (18 )console .log (teacher3.name )console .log (teacher3.age )
class类的getter、setter和static 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Xjj { constructor (private _age : number ) { } get age () { return this ._age - 10 ; } set age (age : number ) { this ._age = age+3 ; } } const dj = new Xjj (28 );dj.age = 25 console .log (dj.age )class Girl { static sayLove ( ) { return 'I love you' } } console .log (Girl .sayLove ())
class类的只读属性 1 2 3 4 5 6 7 8 9 10 11 class Person { public readonly _name : string constructor (name : string ) { this ._name = name; } } const person = new Person ('testName' );console .log (person._name )
抽象类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 / 抽象类 abstract class Girls { abstract skill (); } class Waiter extends Girls { skill ( ) { console .log ('大爷1' ) } } class BaseTeacher extends Girls { skill ( ) { console .log ('大爷2' ) } } class SeniorTeacher extends Girls { skill ( ) { console .log ('大爷3' ) } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 abstract class Component <T1 , T2 > { props : T1 ; state : T2 ; constructor (props : T1 ) { this .props = props } abstract render (): string } interface Props { val : number } interface State { x : number } interface Log { getInfo (): string } interface Save { save (): void } class MyComponent extends Component <Props , State > implements Log , Save { constructor (props : Props ) { super (props) this .state = { x : 1 } } render ( ) { return '<MyComponent>' } getInfo (): string { return '' } save ( ) { } } const myComponent = new MyComponent ({ val : 1 })myComponent.render ()
联合类型和类型保护 联合类型 指某个参数可以是多种类型。
类型保护 指参数属于某个类型才有相应的操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 interface Waiter { anjiao : boolean say : () => {} } interface Teacher { anjiao : boolean skill : () => {} } function judgeWho (animal : (Waiter | Teacher) ) { if (animal.anjiao ) { (animal as Teacher ).skill () } else { (animal as Waiter ).say () } if ('skill' in animal) { animal.skill () } else { animal.say () } } class NumberObj { count : number } function addObj (first : object | NumberObj , second : object | NumberObj ) { if (first instanceof NumberObj && second instanceof NumberObj ) { return first.count + second.count ; } return 0 ; }
枚举 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 enum Status { MASSAGE , SPA , DABAOJIAN } console .log (Status .MASSAGE , Status [0 ]) function getStatus (status : any ) { if (status === Status .MASSAGE ) { return 'massage' } else if (status === Status .SPA ) { return 'spa' } else if (status === Status .DABAOJIAN ) { return 'dabaojian' } } const result = getStatus (Status .SPA )console .log (result)
泛型 泛型,最简单的理解:泛指的类型。(类似函数中的形参与实参)
函数中的泛型使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 function join<JSPang >(first : JSPang , second : JSPang ) { return `${first} ${second} ` } join<string >('jspang' , '123' ); join<number >(11 , 22 ); function myFun<ANY >(params :ANY []) { return params } myFun<string >(['a' , 'b' ]) function join2<T,P>(first : T, second : P) { return `${first} ${second} ` } join2<string ,number >('jspang' , 123 ); join2<number , string >(11 , '22' ); join2 (11 , '22' );
class类中使用泛型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 class SelectGirl <T> { constructor (private girls : T[] ) { } getGirl (index : number ): T { return this .girls [index] } } const selectGirl = new SelectGirl <number >([101 , 102 , 103 ])console .log (selectGirl.getGirl (1 ))interface Girl { name : string } class SelectGirl2 <T extends Girl > { constructor (private girls : T[] ) { } getGirl (index : number ): string { return this .girls [index].name } } const selectGirl2 = new SelectGirl2 ([ {name : '大脚1' }, {name : '大脚2' }, {name : '大脚3' } ]) console .log (selectGirl2.getGirl (1 ))
类型保护 我们通常在 JavaScript 中通过判断来处理⼀些逻辑,在 TypeScript 中这种条件语句块还有另外⼀
个特性:根据判断逻辑的结果,缩⼩类型范围(有点类似断⾔),这种特性称为 类型保护 ,触发条
件:
typeof 1 2 3 4 5 6 7 8 9 10 11 function fn (a : string |number ) { a.substring (1 ); if (typeof a === 'string' ) { a.substring (1 ); } else { a.toFixed (1 ); } }
instanceof 1 2 3 4 5 6 7 function fn (a : Date |Array <any > ) { if (a instanceof Array ) { a.push (1 ); } else { a.getFullYear (); } }
in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 interface IA { x : string ; y : string ; } interface IB { a : string ; b : string ; } function fn (arg : IA | IB ) { if ('x' in arg) { arg.x ; arg.a ; } else { arg.a ; 字⾯量类型保护 如果类型为字⾯量类型,那么还可以通过该字⾯量类型的字⾯值进⾏推断 ⾃定义类型保护 有的时候,以上的⼀些⽅式并不能满⾜⼀些特殊情况,则可以⾃定义类型保护规则 arg.x ; } }
字面量类型保护 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 interface IA { type : 'IA' ; x : string ; y : string ; } interface IB { type : 'IB' ; a : string ; b : string ; } function fn (arg : IA | IB ) { if (arg.type === 'IA' ) { arg.x ; arg.a ; } else { arg.a ; arg.x ; } }
自定义类型保护 1 2 3 4 5 6 7 8 9 10 11 12 function canEach (data : any ): data is Element []|NodeList { return data.forEach !== undefined ; } function fn2 (elements : Element []|NodeList |Element ) { if ( canEach (elements) ) { elements.forEach ((el : Element )=> { el.classList .add ('box' ); }); } else { elements.classList .add ('box' ); } }
data is Element[]|NodeList 是⼀种类型谓词,格式为: xx is XX ,返回这种类型的函数就可以
被 TypeScript 识别为类型保护
类型操作 typeof 获取数据的类型
1 2 3 4 5 6 let str = 'kkk' let t = typeof str type myType = typeof str
keyof 获取类型的所有key的集合
1 2 3 4 5 6 7 8 interface Person { name : string ; age : number ; } type PersonKeys = keyof Person
1 2 3 4 5 6 7 8 9 10 let p1 = { name : 'xx' , age : 28 } function getPersonVal (k : keyof typeof p1 ){ return p1[k] }
in 内部使用for...in对类型进行遍历
1 2 3 4 5 6 7 8 9 10 11 interface Person { name : string ; age : number ; } type PersonKeys = keyof Person ; type NewPerson = { [k in PersonKeys ]: string }
配置文件tsconfig.json 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 { "compilerOptions" : { "target" : "es5" , "module" : "commonjs" , "sourceMap" : true , "outDir" : "./build" , "rootDir" : "./src" , "strict" : true , "esModuleInterop" : true } }
来源:本文导入自 xugaoyi/vuepress-theme-vdoing 的 docs/01.前端/40.学习笔记/35.TypeScript笔记.md。 原作者:xugaoyi。许可证:MIT 。