TypeScript入门知识

1. 基础

TypeScript 是 JavaScript 的一个超集,主要提供了类型系统和对 ES6 的支持.

它可以编译成纯 JavaScript。编译出来的 JavaScript 可以运行在任何浏览器上。

我们约定使用 TypeScript 编写的文件以 .ts 为后缀,用 TypeScript 编写 React 时,以 .tsx 为后缀。

ts 在对数值类型的定义的区别是:
在定义数据类型的时候,都是通过在变量的后面加冒号(:)+数据类型,来限定该变量的应该是一个什么数据类型的变量,当你对该变量进行初始化或者重新赋值时,假如数据类型和定义的不一样,这时ts就会在编译时报错。

let val :number=6;
let new:boolean=false;
let name:string ='Tom';
// 模板字符串
let sentence:string=`Hello,my name is ${name}`;
let u:undefinede=undefined;
let n:null=null;

TypeScript 只会进行静态检查,如果发现有错误,编译的时候就会报错。
TypeScript 编译的时候即使报错了,还是会生成编译结果

undefined和null是所有类型的子类型

而子类型赋值给父类型的变量,是不会报错的,反之则会;

undefined 类型的变量只能被赋值为 undefined,null 类型的变量只能被赋值为 null。

let num:number=undefined;
let str:string =null;
空值(void类型)

在 TypeScript 中,可以用 void 表示没有任何返回值的函数:

function alertName():void{
    alert('My name is Tom');
}

定义变量也可以把变量定义成void类型,但一般没什么用,因为你只能将它赋值为 undefined 和 null。

let unusable:void=undefined;

注意:
void 类型的变量不能赋值给 number 类型的变量

let u:void;
let num:number=u;
//编译会报错
任意值类型

如果数据类型定义的是 any 类型,则允许被赋值为任意类型。
在任意值上访问任何属性都是允许的,也允许调用任何方法。

//  访问属性
let anything:anny='hello';
console.log(anything.myName);
console.log(anything.myName.firstname);
// 调用方法
let antThing:any='Tom';
anyThing.setName('Jerry');
anyThing.myName.setFirstName('Cat');

声明一个变量为任意值之后,对它的任何操作,返回的内容的类型都是任意值

未声明类型的变量

变量如果在声明的时候,未指定其类型,那么它会被识别为任意值类型:

let something;
somethig='seven';
something=7;
somthing.setName('Tom');
什么是类型推论?

如果没有明确指定某个变量的数据类型,那么ts会依照类型推论,推断出一个类型;

当变量定义的时候有赋值的话,那么第一个赋值的类型就会被推测为该变量的类型,之后如果定义的类型与初始赋值的类型不一致,就会报错;如果定义的时候没有赋值,那么该变量就会被识别为any类型,之后有没有赋值,改变量都不会被类型检查。

let val ='zhuzhuxia';
val=7;     //报错

let val2;
val2='zhuzhzuxia';
val2=6;  //不会被类型检查,不会报错
联合类型

表示取值可以为多种类型中的一种。

使用 | 分隔每个类型。

let num:string|number;
num='seven';
num=7;
// 这里表示num的数据类型可以是string或者number的一种;

联合类型的变量在被赋值的时候,会根据类型推论的规则推断出一个类型

接口

是对行为的抽象,而具体如何行动需要由类(classes)去实现(implements)

TypeScript 中的接口,除了可用于对类的一部分行为进行抽象以外,也常用于对「对象的形状(Shape)」进行描述。

下面是定义接口的实例:

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

let tom:Person={
    name:'tom';
    age:24
};

上面的例子中,我们定义了一个接口 Person,接着定义了一个变量 tom,它的类型是 Person。这样,我们就约束了 tom 的形状必须和接口 Person 一致。

定义的变量比接口少了一些属性是不允许的,多一些属性也是不允许的.

赋值的时候,变量的形状必须和接口的形状保持一致

#### 可选属性

有时候我们希望不要完全匹配一个形状,那么可以把我们希望可选的属性,定义成可选属性;

可选属性:该属性可以不存在。但接口任然不允许添加未定义的属性。

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

let tom:Person={
    name:'tom';
    age:24;
}

let tom:Person={
    name:'tom';
}
任意属性

假如你希望你的接口允许有任意的属性,可以将接口定义为如下格式:

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

需要注意的是,一旦定义了任意属性,那么确定属性和可选属性的类型都必须是它的类型的子集:

只读属性

有时候我们希望对象中的一些字段只能在创建的时候被赋值,那么就可以用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 read-only property.",

注意,只读的约束存在于第一次给对象赋值的时候,而不是第一次给只读属性赋值的时候

数组类型

数组的定义方式有多种:
1)[类型+方括号]表示法

let fibonacci: number[] = [1,4,3,4,6,7]; 

    <!-- 联合类型和数组的结合 -->
    let fal: (number|string)[]=[1,5,6,'4','8',0];

    //    数组泛型
      let finb: Array<number>=[1,2,3,4,5,3];

    //  用接口表示数组
    interface NumberArray{
        [index:number]:number;
    } 

    let fibarray: NumberArray=[1,3,4,5,67,5,8];

    // any在数组中表示允许出现任何类型

    let list:any[]=['Xcat Liu':25,{website:'http:xacdliu.com'}];