Typescript学习手札(持续更新)

前言

    作为大前端浪潮中激流勇进的小码农,持续性的去更新自己的技术栈,是极其重要与必要的。作为浪尖上的typescript,新晋之星vue也迈开兼容推广ts的步伐,更是让人必须去see一see的了。记得在vue爬坑之路时,曾在sf遇到个前端大牛说过,老鸟都是从菜鸟过来的,学习的整理和积累是不断成长起来的利剑。这也是我在整理学习手札的原因之一。

正文

学习主要以文档为主,参考ts官方文档
https://www.tslang.cn/docs/ha…

1. 数据类型及变量声明

    ts变量声明定义语法 let[作用规则] param[变量名]:String[类型名] = value[值]
    ts相较原生js,数据类型明显细化了很多,增加了数据类型校验,使编码更规范,个人感觉更像java了。ts提供的类型主要包括: 布尔值(boolean)、字符串(string)、数值(number)、数组([] || Array<>)、元组([dataType,number])、枚举(Enum)、Any(any)、Void(void)、Null(null)、Underfined(underfined)、Never(never)、Object(object

    类型断言(<> || as)类似java的类型转换,主要有两种写法,一种是<>语法

let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;

另一种是 as语法

let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;

    确定赋值断言允许!放置在属性或变量声明之后,ts在解析时,明确声明变量或属性是有值的,例如:let x!:number,变量x后置!,未赋值直接引用x!没毛病;而?则和!相对,ts在解析时会提示可能为underfined;

    letconst是es6引进的两个重要的关键字,引进之前,变量的声明主要是varvar作用域可以是包含它的函数、模块、命名空间或全局域,可以在作用域的任意位置访问该声明。var声明不在乎多少次,因此在很多逻辑比较复杂,层次比较深的代码中,很容易出现同一个变量重复声明重定义覆盖而不报错,这也是一个较为头疼的BUG。
    let则是词法或块作用域,此作用域更贴切逻辑处理时的严谨;const的作用域和let一样,只是const一般作只读声明,主要用于声明常量,引用的值不可改变。

2. 接口

    官方定义,接口的作用是为那些对值所具有结构进行检查的类型命名和为你的代码或第三方代码定义契约。
    声明形式:

interface ifName{
}

    接口是面向对象编程和程序设计一个极为重要的工具。ts中接口的实用与java比较相似(或许jdk就是js的超集导向吧~_~)。ts接口主要可以分为属性类型、函数类型、可索引类型和类类型。

    
属性对象类型

    ts接口只关注值的外形,这也是ts接口的独到之处。类检查器在检查方法调用时,编译器会检查引用对象是否满足接口的要求,即是否包含接口属性且类型是否匹配。

    一般属性声明:

interface ifName{
    name:string
}

    可选属性 是非必须的,可以作为可能出现的属性预定义,即引用对象可根据需求决定是否需要实现(虽然官网不推荐这个词)接口可选属性:

interface DomItem{
    name?: string,
    value?: string
}
function getDom(ifObj: DomItem):{value: string, color: string}{
    console.log(ifObj.value)
}
let dom = getDom({color:'red'})

    只读属性 readonly如其名,定义后不可修改,和const的性质相似,区分在于readonly声明属性,const声明常量:

interface DomItem{
    readonly name: string,
    readonly value: string
}
let dom: DomItem = {name: '节点', value: '1'};
dom.value = '2'; //Error,只读属性不能被修改

    额外属性检查 是一个查错机制,说白了就是传参类型不匹配,例如:

interface DomItem{
    name?: string,
    value?: string
}
function getDom(ifObj: DomItem):{value: string, color: string}{
    console.log(ifObj.value)
}
let dom = getDom({name: '节点', vla:'1'})//Error

可以发现调用getDom()传参对象属性与getDom声明时的参数对象属性不一致,与其说是新的属性,倒不如说是个新类型,因此这边需要对方法调用的参数做类型转换:

let dom = getDom({name: '节点', vla:'1'} as DomItem) 

或者:

let dom = getDom(<DomItem>{name: '节点', vla:'1'}) 

    
函数类型

    函数类型和属性类型不同,描述的是函数,方法是给接口定义一个调用签名,包括参数列表和返回值类型。

interface GetDom{
    (name: string, value: string): object
}

let getDom: GetDom;
getDom = function(name: string, value: string):object{
    //...
}

    函数参数列表里的参数会被逐个进行检查,参数名可以不用相同,参数类型和返回值类型必须能够兼容,或者无需定义,ts的类型系统会推断出参数类型和返回值类型,并做出相应的处理。例如,上面的方法可以重写为:

let getDom: GetDom;
getDom = function(n, v){
    //...
}

或者:

let getDom: GetDom;
getDom = function(n: any, v: any): any{
    //...
}

    
可索引类型

    可索引类型描述的是具有索引属性的类型,最直观的例子是数组。可索引类型需要定义索引签名,包括索引类型和返回值类型。

interface Dom{
    [x: string]: string
}
let dom: Dom= {
    name: '节点'
}
interface DomArray{
    [index: number]: string
}
let domArray: DomArray= ['city','country']

    索引的类型有两种,字符串和数值。字符串索引是对对象数据的约束,数值索引是对数组数据的约束,个人感觉可索引类型的应用场景会比较少,js已经存在属性写法,没必要额外添加约束,可能有我没遇到的特例,欢迎指出。

    
混合类型

    混合类型是以上几种的集成形式,既可以描述函数,也可以描述属性对象,使用起来比较灵活。

interface DomHandle{
    (name: string): string,
    name: string,
    reset: void
}
let domHandle = function(){
    let domHandle = function(name: string): DomHandle;
    domHandle.name = 'dom';
    domHandle.reset = function(){
        //...
    }
}
let d = domHandle(); 

3. 函数

    函数被用来定义行为,ts和js一样,分为具名函数和匿名函数。

/*---function声明---*/
function getDom1(): string {
    return 'inode'
}

/*---函数类型声明---*/
let getDom2: () => string //此处=>标识返回类型,并非es6的箭头函数,需要做区分,不能混淆

/*---变量别名类型推断式声明---*/
let getDom3 = (): void => {
}

/*---接口类型声明---*/
interface GetDom4 {
    (n: string, v: string): string
}

    
函数参数

    和js相比,ts函数在传参时必须满足声明时参数列表的要求,即传参列表的数量和类型要和声明函数的参数列表一致。

    js中函数调用时若未传参,它的值会是underfined,若要达到这样的效果,可以在参数变量后置?或者声明时给出默认值来达到可选参数的效果。注意:必选参数必须在可选参数之前!

/*--- 可选参数 ---*/
function getDom1(name: string, value: string): string {
    return 'inode'
}

/*--- 默认参数 ---*/
function getDom2(value = '1', name: string): string {
    return 'inode'
}
let result = getDom2(underfined, 'node')

    共享参数类型时,默认参数即为可选参数的类型。
    如果参数未知切数量不定时,可以使用剩余参数语法,剩余参数可以被当做个数不定的可选参数。

/*--- 剩余参数 ---*/
function getDom1(name: string, ...params): string {
    return 'inode'
}

    this指针是老生常谈的话题了,无论是浸淫js多年的牛牛们,还是业界新入的白白们,this指向问题都是避免不了的。详细讲解链接https://yehudakatz.com/2011/0…this是在函数调用时确定值,一般指向函数调用的对象,如果没有调用对象,this值为window(严格模式下是underfined);es6一般使用箭头函数来声明定义,箭头函数中的this的值是定义中this的值,而不是函数调用时的this值。

    函数重载

    函数重载通过统一个函数来进行多个函数定义来处理不同类型的数据。
注意:定义重载时一定要把最精确的定义放在最前面

/* 函数重载 */
function getDom(name?: string): void;
/* 下面函数有实现,所以不需要declare关键字 */
function getDom(name = '1'):any {//此处x参数为共享状态类型,默认参数将转换为可选参数
    //...
}
    原文作者:Fury
    原文地址: https://segmentfault.com/a/1190000020263210
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞