@@ -103,7 +103,7 @@ const newData = JSON.parse(rowData)
103
103
但是这种情况我们使用编辑器将鼠标放置在` newData ` 上我们会发现` ts ` 无法推断出` newData ` 的类型,结果为` any ` ,像这种使用内置函数方法的情况,我们可以这样处理:
104
104
``` ts
105
105
interface Person = {
106
- name: ' string' ,
106
+ name: ' string' ;
107
107
}
108
108
const rowData = ' {"name": "haochyk"}'
109
109
const newData: Person = JSON .parse (rowData )
@@ -214,8 +214,8 @@ const objectArr: { name: string, age: number }[] = [
214
214
如果我们的对象内容非常多的话,这样写代码就显的非常不美观了,我们可以使用类型别名(` type alias ` )来解决这个问题:
215
215
``` ts
216
216
type User = {
217
- name: string ,
218
- age: number ,
217
+ name: string ;
218
+ age: number ;
219
219
}
220
220
const objectArr: User [] = [
221
221
{
@@ -227,8 +227,8 @@ const objectArr: User[] = [
227
227
值得我们注意的是` class ` 类,` TS ` 不会强制要求必须返回实例对象,所以只要数据内容格式一致都是被允许的,比如以下这种写法:
228
228
``` ts
229
229
class User = {
230
- name: string ,
231
- age: number ,
230
+ name: string ;
231
+ age: number ;
232
232
}
233
233
const objectArr: User [] = [
234
234
new User (),
@@ -261,4 +261,272 @@ const userInfo: ( string | number )[] = ['haochy', 'male', 18]
261
261
const userInfoList: [string , string , number ][] = [
262
262
[' haochyk' , ' male' , 18 ],
263
263
]
264
+ ```
265
+ ## Interface接口
266
+ 首先我看来看一段代码,我们通过代码来讲解interface的具体知识点。
267
+ ``` ts
268
+ function getPersonName (person : { name: string }) {
269
+ console .log (person .name )
270
+ }
271
+ function setPersonName (person : { name: string }, name : string ) {
272
+ person .name = name
273
+ }
274
+ ```
275
+ 上面两个简单的方法我们可以看出person参数后的类型定义我们需要重复的写两边,这个时候我们将重复的类型定义用interface接口的形式抽离出来:
276
+ ``` ts
277
+ interface Person {
278
+ name: string ;
279
+ age: number ;
280
+ }
281
+ function getPersonName (person : Person ): void {
282
+ console .log (person .name )
283
+ }
284
+ function setPersonName (person : Person , name : string ): void {
285
+ person .name = name
286
+ }
287
+ ```
288
+ 当然还有另外一种方法可以实现相通的效果就是使用类型定义:` type alias ` :
289
+ ``` ts
290
+ type Person = {
291
+ name: string ;
292
+ age: number ;
293
+ }
294
+ function getPersonName (person : Person ): void {
295
+ console .log (person .name )
296
+ }
297
+ function setPersonName (person : Person , name : string ): void {
298
+ person .name = name
299
+ }
300
+ ```
301
+ ` interface ` 和` type ` 类似但又不完全相同,不同点就是interface只能代表一个函数或者一个对象,它不能代表一个基础类型:
302
+ ``` ts
303
+ type Person = string
304
+ interface Person {
305
+ name: string ;
306
+ age: number ;
307
+ }
308
+ ```
309
+ ::: tip 提示
310
+ 在` TypeScript ` 里面一个通用型的规范就是:如果能用接口来表述一个别名的话我们就用接口的方式,实在不行我们才用类型别名
311
+ :::
312
+ 在有些情况下我们不需要传递` age ` 属性该怎么办,我们不传递` age ` 参数` ts ` 又会报错,我们可以这样来写:
313
+ ``` ts
314
+ interface Person {
315
+ readyonly name: string ;
316
+ age? : number ;
317
+ }
318
+ ```
319
+ 这样的意思就是` age ` 属性可有可无,还有一个修饰符:` readonly ` 意思为属性只读。
320
+ 这里值得我们注意的一点就是,如果我们传递参数的时候,多传递了一个` sex ` 属性:
321
+ ``` ts
322
+ interface Person {
323
+ name: string ;
324
+ age: number ;
325
+ }
326
+ function getPersonName (person : Person ): void {
327
+ console .log (person .name )
328
+ }
329
+ function setPersonName (person : Person , name : string ): void {
330
+ person .name = name
331
+ }
332
+ const person = {
333
+ name: ' haochyk' ,
334
+ sex: ' male' ,
335
+ }
336
+ // 不会报错
337
+ getPersonName (person )
338
+ // 报错
339
+ getPersonName ({
340
+ name: ' haochyk' ,
341
+ sex: ' male' ,
342
+ })
343
+ ```
344
+ 这是因为,我们如果直接使用字面量的形式传参的话,` ts ` 会进行强校验,必须严格符合参数的类型定义,而如果我们使用缓存的形式,则不会,只要有类型定义该有的东西即可,多出一点东西也是可以的。
345
+ 如果我们只是确定参数对象有` name ` 属性,我们不确定有其他属性的时候我们可以这样来写:
346
+ ``` ts
347
+ interface Person {
348
+ readyonly name: string ;
349
+ age? : number ;
350
+ [propName : string ]: any ;
351
+ }
352
+ ```
353
+ 接口里不仅可以存这样的属性和它的类型还可以存方法,比如我们定义` say ` 方法返回值的类型为` string ` :
354
+ ``` ts
355
+ interface Person {
356
+ readyonly name: string ;
357
+ age? : number ;
358
+ [propName : string ]: any ;
359
+ say(): string ;
360
+ }
361
+ ```
362
+ ` Class ` 类是可以应用接口的,当一个类去应用接口时必须拥有接口里的属性,举个例子:
363
+ ``` ts
364
+ class user implements Person {
365
+ name = ' haochy' ;
366
+ say () {
367
+ return ' hello'
368
+ }
369
+ }
370
+ ```
371
+ 接口之间还可以互相继承,如下面这个例子:
372
+ ``` ts
373
+ interface Teacher extends Person {
374
+ teach(): string
375
+ }
376
+ const teacher = {
377
+ name: ' haochyk' ,
378
+ age: 18 ,
379
+ say () {
380
+ return ' hello'
381
+ },
382
+ teach () {
383
+ return ' TypeScript'
384
+ }s
385
+ }
386
+ setPersonName (teacher , ' haochyk' )
387
+ ```
388
+ 接口继承它会拥有` Person ` 接口下所有的属性和方法,同时还必须得有自己的属性或方法。
389
+ 接口自身除了可以定义属性、方法之外,其实它自身还可以定义函数:
390
+ ``` ts
391
+ interface SayHi {
392
+ (word : string ): string
393
+ }
394
+ const say: SayHi = (word ) => {
395
+ return word
396
+ }
397
+ ```
398
+ 同样` interface ` 还可以定义数组这样的索引类型,当我们去写这种接口的时候,` ts ` 最终会把把文件编译成js,但是最终编译后的` js ` 内并没有` interface ` 。
399
+ ::: danger 注意
400
+ 其实,` interface ` 就是在我们开发过程中` TypeScript ` 帮助我们做语法提示的一个工具。真正编译的时候会将这部分内容剔除掉。
401
+ :::
402
+ ## 类的定义与继承
403
+ ` TypeScript ` 中的类其实和` JavaScript ` 、` ES6 ` 中的类很类似,不过在它的基础上` TypeScript ` 提供了更多的特性.
404
+ 我们先看一个最基础的类:
405
+ ``` ts
406
+ class Person {
407
+ name = ' haochyk' ;
408
+ getName () {
409
+ console .log (this .name )
410
+ }
411
+ }
412
+ ```
413
+ 有了类之后我们可以通过类来创建一个实例,比如说:
414
+ ``` ts
415
+ class Person {
416
+ name = ' haochyk' ;
417
+ getName () {
418
+ return this .name
419
+ }
420
+ }
421
+ const person = new Person ()
422
+ ```
423
+ 到这里我们就说了如何去定义一个类,以及如何在类里去定义方法。
424
+ 接着我们来说下类的继承:(在` ES6 ` 里写类的继承其实是和` TypeScript ` 里是一样的)
425
+ ``` ts
426
+ class Person {
427
+ name = ' haochyk' ;
428
+ getName () {
429
+ return this .name
430
+ }
431
+ }
432
+ class Teacher extends Person {
433
+ getTeacherName () {
434
+ return ' hao'
435
+ }
436
+ }
437
+ const teacher = new Teacher ()
438
+ console .log (teacher .getName ()) // haochyk
439
+ console .log (teacher .getTeacherName ()) // hao
440
+ ```
441
+ 继承的意思就是,子类不仅可以使用父类的方法还可以使用自己的方法。
442
+ 类还有一个概念叫做重写,即在子类和父类中的同名方法,子类中的方法会覆盖掉父类中的方法,如果想要调用父类中的方法,我们可以使用` super ` ,例如:
443
+ ``` ts
444
+ class Teacher extends Person {
445
+ getName () {
446
+ return super .getName () + ' 1'
447
+ }
448
+ }
449
+ console .log (teacher .getName ()) // haochyk1
450
+ ```
451
+ 这同样也是` super ` 在开发中常用的应用场景:子类重写父类方法,如果需要调用父类方法可以使用` super `
452
+ ## 类中的访问类型和构造器
453
+ ### 访问类型
454
+ 什么是访问类型?我们在` ts ` 中定义一个类,我们实例化这个类,访问以及修改这个实例中的属性都是可以的,因为` ts ` 中类的属性默认是` public ` 访问类型。
455
+ 访问类型分为三种:` private ` 、` protected ` 、` public ` 。<br />
456
+ * ` private ` : 仅在类内允许被调用
457
+ * ` protected ` :类内或者继承的子类中允许被调用
458
+ * ` public ` :类内外都可以允许被调用
459
+ 我们通过代码来看下这三个的区别:<br />
460
+ 首先` private ` :
461
+ ``` ts
462
+ class Person {
463
+ private name = ' haochyk'
464
+ say () {
465
+ return this .name // 允许访问
466
+ }
467
+ }
468
+ const person = new Person ()
469
+ console .log (person .name ) // ts报错
470
+ ```
471
+ ` public ` :
472
+ ``` ts
473
+ class Person {
474
+ public name = ' haochyk'
475
+ say () {
476
+ return this .name // 允许访问
477
+ }
478
+ }
479
+ const person = new Person ()
480
+ console .log (person .name ) // 允许访问
481
+ ```
482
+ ` protected ` :
483
+ ``` ts
484
+ class Person {
485
+ protected name = ' haochyk'
486
+ say () {
487
+ return this .name // 允许访问
488
+ }
489
+ }
490
+ class Teacher {
491
+ teacherSay () {
492
+ return this .name // 允许访问
493
+ }
494
+ }
495
+ const person = new Person ()
496
+ console .log (person .name ) // ts报错
497
+ ```
498
+ ### 构造器 (constructor)
499
+ 老样子,我们先来定义一个类:
500
+ ``` ts
501
+ class Person {
502
+ public name: string
503
+ constructor (name : string ) {
504
+ this .name = name
505
+ }
506
+ }
507
+ const person = new Person (' haochyk' )
508
+ console .log (person .name ) // haochyk
509
+ ```
510
+ ` constructor ` 这个方法会在类被实例化的时候自动执行,并且将实例化的参数传递给` constructor ` 这个方法。
511
+ 以上例子是比较传统的写法,我们先定义一个属性,然后在构造器中给属性赋值,` ts ` 提供了一个更简单的方法,这两种写法是等价的:
512
+ ``` ts
513
+ class Person {
514
+ constructor (public name : string ) {}
515
+ }
516
+ const person = new Person (' haochyk' )
517
+ console .log (person .name ) // haochyk
518
+ ```
519
+ 如果继承中,子类要使用构造器,需要使用` super ` ,这时` super ` 是一个方法,它代表父类的构造函数,同时需要将父类构造函数需要的参数传递给` super ` 方法,即便父类没有构造器,子类也需要调用一个参数为空的` super() ` ,代码如下:
520
+ ``` ts
521
+ class Person {
522
+ constructor (public name : string ) {}
523
+ }
524
+ class Teacher {
525
+ constructor (public age : number ) {
526
+ super (' haochyk' )
527
+ }
528
+ }
529
+ const teacher = new Teacher (18 )
530
+ console .log (teacher .name ) // haochyk
531
+ console .log (teacher .age ) // 18
264
532
```
0 commit comments