TypeScript笔记(1)

类型

基本类型

TypeScript与JavaScript的区别就是TypeScript更加严谨,这里的严谨体现在对每一个变量的类型要求上,定义这个变量是,就要定义这个变量的类型,而在JavaScript中,变量主要有5个原始数据类型。

布尔值,数值,字符串,null,undefined。(正经来说,对象也是一个原始数据类型,但是在ts中,对象和前几个规则差的很多,所以等下再说,还有Symbol,在日常中我并不怎么使用这个东西,所以按下不表)

let Boo: boolean = false;

Boo是变量名,在变量名后面跟冒号,冒号后面是数据类型。

其中boolean是布尔值的意思,同理字符串值使用的string,数值使用的是number,null和undefined使用的都是分别是null和undefined。

这里要多说一句,null和undefined是所有类型的子类型,既number类型的值可以是null或者undefined。

let u: undefined;
let num: number = u;

//这样是合法值

与JavaScript不同的是,在TypeScript中,还有空值的概念,既当一个函数不返回任意一个值的时候,他返回的是空值,在这里空值用void声明。

function test(): void{
    console.log('test')
}

当有返回值的时候,我们就需要给返回值设定一个类型

let num: number = 55 
function renum(num): number{
    console.log(num);
    return num
}

特殊类型

在所有的类型之外,还有一个类型的叫任意值类型。这种类型的变量可以被赋予任意类型的值。

let num: any = 55;
num = 'five'

这样是合法的。并且可以调用所有类型的所有方法,ts并不做检查,虽然最后执行可能还是报错,但是在ts这里是合法的,例

let num: any = 55;
console.log(num.sayhi())

这样的代码是可以通过ts的检查的,但是他实际是无法运行的,因为num只是一个变量,没有sayhi方法。

当不注明具体类型的时候,变量会被ts识别为any类型。

这里有两种情况,一个是在声明的时候直接赋予值,另一种是先声明,然后赋予值,例

let num = 'five';
num = 5;

//这样会报错

let num;
num = 'five';
num = 5;

//这样不会报错

为什么呢?因为ts还有一套类型推论,如果再声明的时候是

let num = 'five';

是等价于

let num: string = 'five';

let num;

则等价于

let num: any;

故而前者是字符串类型,后者是任意类型。

那么如果变量可能有两个类型,我们是不是就必须用any类型了呢?ts还提供了一种联合类型供我们使用。

let numstring: number | string;
numstring = 55;
numstring = 'five'

但是这里要注意,当我们调用该变量的属性的时候,只能调用这两个变量的共有属性,而不能调用他们各自独有的,既

function test(a: number | string): number{
    return a.length
}

是不合法的,因为number类型并没有length属性。如果想要合法,就要删掉a的number类型。

function test(a: string): number{
    return a.length
}

这样就是合法的了。

对象类型

刚刚我们说了对象类型和其他类型不太一样,那么哪里不一样呢?对象类型需要引入一个接口的概念。这里的接口不是用于和后端交互的,而是一个对象的属性规则,用于前端的交互。

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

这样就做了一个人接口,在使用的时候,我们就需要按照人接口给出的规则创建个体人。

let tom: Person = {
    name: 'Tom',
    age: 25
};

其实可以把人这个接口看做前面的类型,既Person在这里和number是类似的。不同的是,接口字母需要大写,这个不是强制要求。

在上面那个Person的规定下,人必须有两个属性,不能多也不能少,这样就很局限了,所以TypeScript还提供了可选属性与任意属性。

先说可选属性,可选属性就是在冒号前面添加一个问号,ts就会认为这个属性是可选属性。

interface Person {
    name: string;
    age?: number;
};

let tom: Person = {
    name: 'Tom'
};

再说任意属性,这里有一个问题,那就是可选属性其实就是任意属性,当我们任意属性的键名为可选属性的键名时,他就等同于可选属性。所以任意属性是比可选属性等级更高的,则可选属性的类型必须是任意属性的子类型,既

interface Person {
    name: string;
    age?: number;
    [propName: string]: string;
}

let tom: Person = {
    name: 'Tom',
    age: 25,
    gender: 'male'
};

对于这段代码来说,因为可选属性age的类型是number,而任意属性的类型是string,所以当我们创建一个名为age属性的时候,ts并不会去找可选属性,而是首先查看任意属性的类型,因为任意属性的类型是string,所以ts无法编译这边代码。

所以可选属性的类型必须是任意属性类型的子属性。

说完了初始化属性,我们还要考虑权限问题,有一些属性我们是不希望更改的,也就是只读属性,

interface Person {
    readonly id: number;
    name: string;
    age?: number;
    [propName: string]: any;
}

let tom: Person = {
    id: 89757,
    name: 'Tom',
    gender: 'male'
};

tom.id = 9527;

这个就没什么好解释的了,很简单的东西,看一下就好了。

数组类型

数组类型通过类型+方括号来表示

let num: number[] = [1,2,3,4];

其中num是数组名,number是数组类型,所以在名为num的数组中是不允许有number类型以外的东西存在的。

函数类型

函数也很简单,因为函数是有输入,有输出的,所以我们不仅要限定输入,也要对输出限制

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

如果函数没有返回值,那么函数的返回值类型为void。

函数还有另一种写法

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

这里的箭头函数(=>)不是es6的箭头函数,而是TypeScript的函数定义,随着es7,es8的完善,TypeScript可能会跟进这些改变,所以我个人不太喜欢这种写法,容易搞混。

函数还可以用之前说到的接口来定义

interface Sum {
    (source: number, subString: number): number;
}

let sum: Sum;
sum = function(add, otheradd) {
    return add + otheradd;
}

这里肯定有人要问了,如果我在函数自变量处强行规定另一种类型会怎么样呢?

例如

interface Sum {
    (source: number, subString: number): number;
}

let sum: Sum;
sum = function(add: string, otheradd) {
    return add + otheradd;
}

console.log(sum('456',555))

这样编译会报错,这里的规则只看接口,因为已经规定好了这个函数的出和入的变量类型,所以后续再更改是无效的。这条规则也是ts的基础规则,既一旦设定类型,就不能再更改。

上面这些都是设定的很死的规则,对象类型都有可选属性,难道作为一等公民的函数会没有嘛,当然不,下面说一下可选参数

function connection (one: string, otherone?: string) {
    return one + '' + otherone;
}

这样第二个参数就是一个选填的参数。

这里要注意一点,那就是选填的参数不能在必填参数前面,否则ts没办法判断到底是必填参数还是选填参数。

既然有了可选参数,那么在es6中的参数默认值也是有的,用法和es6也一致。

function connection (one: string = 'one', otherone?: string) {
    return one + '' + otherone;
}

和js中有剩余参数的说法,既

function sum(add, ...items) {
    let sum = add;
    items.forEach(function(item) {
        add = add + item
    });
    return add;
}
let a = sum(0,1,2,3,4)
// a = 10

在TypeScript中,基本沿用了es6中的规定,不同的是,TypeScript多了一个类型的规定

function sum(add: number, ...items: number[]) {
    let sum = add;
    items.forEach(function(item) {
        add = add + item
    });
    return add;
}
let a = sum(0,1,2,3,4)
// a = 10

这里要强调的一点是,items是一个数组,而不是单独的某个数,所以这里对items的类型定义是成分数值类型的数组。

写到这里有经验的前端程序员就应该已经看出来TypeScript的优势了,数值可以相加,数值和字符串也可以相加,但是这时候就并不是我们想要的结果了,而TypeScript可以很好的解决这个问题。

断言类型

前面说到复合类型在使用类型的属性的时候,只能使用共有属性,而不能使用特有的,但是有的时候我们就是要使用这些类型怎么办呢?这里就要用到断言类型了。

断言类型是手动的指定,假如这个值是这个类型,他不是改变一个值的类型。

function getLength(something: string | number): number {
    if ((<string>something).length) {
        return (<string>something).length;
    } else {
        return something.toString().length;
    }
}

这里的就是断言类型,他假设something这个值是string类型的情况下,执行的东西。

内部对象

JavaScript有很多内部对象大家都是知道的,TypeScript对JavaScript的内部对象的使用也添加了一层规定,让这样的使用变得更加的规范

Math.pow(10, '2');

在JavaScript中,这样的语句是不标准的,但是合法可运行的,但是在TypeScript中,这样是无法通过编译的,要用标准的写法

Math.pow(10, 2);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值