前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >TypeScript进阶

TypeScript进阶

作者头像
刘亦枫
发布2020-03-19 17:26:23
9300
发布2020-03-19 17:26:23
举报

类型断言

类型断言(Type Assertion)是开发者手动指定一个值的类型: <类型>值或值 as 类型

在 tsx 语法(React 的 jsx 语法的 ts 版)中必须使用值 as 类型。

例如:将一个联合类型的变量指定为一个更加具体的类型(但不能指定为联合类型中不存在的类型):

// 使用联合类型时,必须使用这些类型共有的属性才行,但使用类型断言使其确定为某一种类型,就没有了此限制。
function getLength(something: string | number): number {
    if ((<string>something).length) {    //<string>something类型断言为字符串,就可以使用字符串独有的属性方法。
        return (<string>something).length;
    } else {
        return something.toString().length;
    }
}

类型推断:

如果没有明确的指定类型,TS会依照类型推论(Type Inference)的规则推断出一个类型:

let myFavoriteNumber = 'seven';      //无错
myFavoriteNumber = 7;                //Type 'number' is not assignable to type 'string'.

不对其类型进行指定,TS会自动推断为any类型,如果进行了指定,如‘seven’,TS会自动推断为string类型。

注意:与声明不赋值区分,声明不赋值会设为任意值类型:any

类型推论(Type Inference)是指编程语言在编译期中能够自动推导出值的数据类型的能力,它是一些强静态类型语言的特性。

可选参数

同接口的可选属性一样,用 ? 表示可选的参数。

可选参数必须接在必需参数后面,即可选参数后不能有必须参数。

function buildName(firstName: string, lastName?: string) {
    if (lastName) {
        return firstName + ' ' + lastName;
    } else {
        return firstName;
    }
}
let tomcat = buildName('Tom', 'Cat');
let tom = buildName('Tom');

联合类型

联合类型使用 | 分隔每个类型,表示可以赋值为其中的一种。

let myFavoriteNumber: string | number;  //允许 myFavoriteNumber 的类型是 string 或者 number,但是不能是其他类型。
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;           // 无错

注意:当 TS 不确定一个联合类型的变量到底是哪个类型的时候(比如定义一个方法时),我们只能访问此联合类型的所有类型里共有的属性或方法:

function getLength(something: string | number): number {
    return something.length;    //   Property 'length' does not exist on type 'string | number'.
    //  length 不是 string 和 number 的共有属性,所以会报错。
    //  但访问 string 和 number 的共有属性不会报错,如:return something.toString();

当联合类型的变量在被赋值的时候,会根据类型推论的规则推断出一个类型,此时访问该类型的属性不会报错。

对象的类型:接口

在 TS 中,使用接口(Interfaces)来定义对象的类型。

接口Interfaces是对行为的抽象,而具体如何行动是由类classes去实现(implement)。

TS 中的接口是一个非常灵活的概念,除了可用于对类的一部分行为进行抽象以外,也常用于对「对象的形状(Shape)」进行描述。 如:定义一个接口 Person,接着定义一个变量 tan,它的类型是 Person。这样,就约束了 tan 的形状必须和接口 Person 一致(多一些或少一些属性都会报错):

interface Person {
    name: string;
    age: number;
}
let tan: Person = {
    name: 'tan',
    age: 22
};

可选属性(仍然不允许添加接口中没有的属性)

当一个接口中有些属性是不需要的,将其设为可选属性,就可以不要它:

interface Person {
    name: string;
    age?: number;       //设为可选属性   
}
let tan: Person = {
    name: 'tan'
};

任意属性

如果有任意属性,那么确定属性和可选属性的类型都必须是任意属性的类型的子集。

interface Person {
    name: string;
    [propName: string]: any;        //定义了任意属性,取 string 类型,属性值取any类型。
}
let tom: Person = {
    name: 'tan',
    gender: 'male'
};

只读属性

如果要求对象中的一些字段只能在创建的时候被赋值,使用 readonly 定义只读属性(只读的约束存在于第一次给对象赋值的时候,而不是第一次给只读属性赋值的时候)

interface Person {
    readonly id: number;
    name: string;
    age?: number;
    [propName: string]: any;
}
let tom: Person = {
    id: 89757,
    name: 'Tom',
    gender: 'male'
};
tom.id = 9527;      //  Cannot assign to 'id' because it is a constant or a read-only property.

接口继承

接口继承就是说接口可以通过其他接口来扩展自己。

Typescript 允许接口继承多个接口。

继承使用关键字 extends。

单接口继承语法格式:

Child_interface_name extends super_interface_name

多接口继承语法格式:

Child_interface_name extends super_interface1_name, super_interface2_name,…,super_interfaceN_name

继承的各个接口使用逗号 , 分隔。

数组的类型

TS中,数组有多种定义方式。

**方法一:**使用「类型 + 方括号」来表示数组(类型可以是any):

let fibonacci: number[] = [1, 1, 2, 3, 5];  //数组的值只能是number类型
let list: any[] = ['Xcat Liu', 25];  //数组的值可以是任意类型

数组的项不允许出现其他类型,并且数组的一些方法的参数也不能出现其他类型,如:push()。

**方法二:**数组泛型:

let fibonacci: Array<number> = [1, 1, 2, 3, 5];

方法三:用接口描述数组:

interface NumberArray {
    [index: number]: number;   //只要 index 的类型是 number,那么值的类型必须是 number。
}
let fibonacci: NumberArray = [1, 1, 2, 3, 5];

方法四:类数组:

function sum() {
    let args: number[] = arguments;//错误,arguments缺少属性push
}

// index.ts(2,7): error TS2322: Type 'IArguments' is not assignable to type 'number[]'.
//   Property 'push' is missing in type 'IArguments'.

事实上常见的类数组都有自己的接口定义,如 IArguments, NodeList, HTMLCollection 等:

function sum() {
    let args: IArguments = arguments;
}

函数的类型

在 JS 中,有两种常见的定义函数的方式——函数声明(Function Declaration)和函数表达式(Function Expression)。

函数声明:

function sum(x: number, y: number): number {
    return x + y;
}

参数过多或参数不足会报错

函数表达式:

let mySum: (x: number, y: number) => number = function (x: number, y: number): number {
    return x + y;
};

在 TS 的类型定义中,=> 用来表示函数的定义,左边是输入类型,需要用括号括起来,括号右边是输出类型。 在 ES6 中,=> 是箭头函数。

用接口定义函数

接口可以描述对象,数组,同样适用于函数:

interface SearchFunc {     //定义一个接口
    (source: string, subString: string): boolean;
}
let mySearch: SearchFunc;   //定义mySearch类型为SearchFunc
mySearch = function(source: string, subString: string) {
    return source.search(subString) !== -1;
}
// 相当于接口的属性是函数的参数,返回值是接口的属性值。

参数默认值

在ES6中,允许给函数的参数添加默认值,TS 会将添加了默认值的参数识别为可选参数,因此可选参数可以不必须接在必需参数后面。

function buildName(firstName: string = 'Tom', lastName: string) {
    return firstName + ' ' + lastName;
}
let tomcat = buildName('Tom', 'Cat');
let cat = buildName(undefined, 'Cat');

剩余参数

同样在ES6中,可以使用 …rest 的方式获取函数中的所有剩余参数:

function push(array: any[], ...items: any[]) { 
    items.forEach(function(item) {  ////将items的每一项push进array
        array.push(item);
    });
}
let a = [];
push(a, 1, 2, 3);  // a是一个数组,...items就是剩余的参数1,2,3

函数重载

函数重载允许一个函数接受不同数量或类型的参数,并作出不同的处理。

TS 会优先从最前面的函数定义开始匹配,所以多个函数定义如果有包含关系,需要优先把精确的定义写在前面。如:

interface User {
  name: string;
  age: number;
}

declare function test(para: User | number, flag?: boolean): number;

在这个 test 函数里,我们的本意可能是当传入参数 para 是 User 时,不传 flag,当传入 para 是 number 时,传入 flag。TypeScript 并不知道这些,当你传入 para 为 User 时,flag 同样允许你传入:

const user = {
  name: 'Jack',
  age: 666
}

// 没有报错,但是与想法违背
const res = test(user, false);

使用函数重载能帮助我们实现:

interface User {
  name: string;
  age: number;
}

declare function test(para: User): number;
declare function test(para: number, flag: boolean): number;

const user = {
  name: 'Jack',
  age: 666
};

// bingo
// Error: 参数不匹配
const res = test(user, false);

declare只起提示作用,不参与任何逻辑实现,如果调用declare过的方法没有js实现的话会报错。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 类型断言
  • 类型推断:
  • 可选参数
  • 联合类型
  • 对象的类型:接口
  • 数组的类型
  • 函数的类型
  • 参数默认值
  • 剩余参数
  • 函数重载
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档