数组
ts像js一样可以操作数组元素。有两种方式定义数组。
- 可以在元素类型后面接上[],表示由此类型元素组成的一个数组
let list : number[] = [1,2,3]
-
使用数组泛型,Array<元素类型>
let list : Array<number> = [1,2,3]
-
用接口表示数据
interface NumberArray { [index : number] : number } let na : NumberArray = [1,2,3]
NumberArray表示:只要索引的类型是数字时,那么值的类型必须是数字
元组 Tuple
元组类型允许表示一个已知元素数量和类型的数组,个元素的类型不必相同。
当添加越界的元素时,它的类型会被限制为元组中每个类型的联合类型。
枚举 enum
enum类型是对JavaScript标准数据类型的一个补充。使用枚举类型可以为一组数值赋予有好的名字。
enum Color {red,green,blue} let c : Color = Color.red //0
默认情况下,从0开始为元素编号。也可以手动指定成员的数值
enum Color {red = 1,blue = 4,grey} let c : Color = Color.blue //4
枚举值有两种类型:常数项(constant member)和计算所得项(computed member)。
注意:如果紧接在计算所得项后面的是未手动赋值的项,那么它就会因为无法获得初始值而报错。
Any
为在编程阶段还不清楚的变量指定一个类型,这种情况下不希望类型检查器对这些值进行检查而是直接让它们通过编译阶段的检查。
Void
表示没有任何类型。当一个函数没有返回值时,会见到其返回值的类型是void
类型断言(Type Assertion)
类型断言可以用来手动指定一个值的类型。
类型断言好比其他语言里的类型转换,但是不进行特殊的数据检查和解构。它没有运行时的影响,只是在编译阶段起作用。
- 尖括号语法
let str : any = 'zhenjianyu' let strLen : number = (<string>str).length
- as语法
let str : any = 'zhenjianyu' let strLen : number = (str as string).length
类型断言的用途
- 将一个联合类型断言为其中一个类型
- 将一个父类断言为更加具体的子类
- 将任何一个类型断言为any(它极有可能掩盖了真正的类型错误,所以如果不是非常确定,就不要使用as any。一方面不能滥用as any,另一方面也不要完全否定它的作用,我们需要在类型的严格性和开发的便利性之间掌握平衡)
- 将any断言为一个具体的类型
除非迫不得已,千万别用双重断言。(as any as Foo)
类型推论
ts会在没有明确的指定类型的时候推测出一个类型,这就是类型推论。
如果定义的时候没有赋值,不管之后有没有赋值,都会被推断成 any 类型而完全不被类型检查。
联合类型 ( UnionTypes )
联合类型表示取值可以为多种类型中的一种。联合类型使用 | 分隔每个类型。
当ts不确定一个联合类型的变量到底是哪个类型的时候,我们只能访问次联合类型的所有类型里共有的属性和方法。
class & interface
门是一个类,防盗门是门的子类。如果防盗门有一个报警的功能,我们可以简单的给防盗门添加一个报警的方法,这时候如果有另一个类,车也有报警的功能,就可以考虑把报警功能提取出来,作为一个接口,防盗门和车都去实现它。
类的概念
- 类(Class):定义了一件事物的抽象特点,包含它的属性和方法
- 对象(Object):类的实例,通过
new
生成 - 面向对象(OOP)的三大特性:封装、继承、多态
- 封装(Encapsulation):将对数据的操作细节隐藏起来,只暴露对外的接口。外界调用端不需要(也不可能)知道细节,就能通过对外提供的接口来访问该对象,同时也保证了外界无法任意更改对象内部的数据
- 继承(Inheritance):子类继承父类,子类除了拥有父类的所有特性外,还有一些更具体的特性
- 多态(Polymorphism):由继承而产生了相关的不同的类,对同一个方法可以有不同的响应。比如
Cat
和Dog
都继承自Animal
,但是分别实现了自己的eat
方法。此时针对某一个实例,我们无需了解它是Cat
还是Dog
,就可以直接调用eat
方法,程序会自动判断出来应该如何执行eat
- 存取器(getter & setter):用以改变属性的读取和赋值行为
- 修饰符(Modifiers):修饰符是一些关键字,用于限定成员或类型的性质。比如
public
表示公有属性或方法 - 抽象类(Abstract Class):抽象类是供其他类继承的基类,抽象类不允许被实例化。抽象类中的抽象方法必须在子类中被实现
- 接口(Interfaces):不同类之间公有的属性或方法,可以抽象成一个接口。接口可以被类实现(implements)。一个类只能继承自另一个类,但是可以实现多个接口
注意如果 readonly
和其他访问修饰符同时存在的话,需要写在其后面。
interface
可用于对类的一部分行为进行抽象以外,也常用于对「对象的形状(shape)」进行描述。接口一般首字母大写。有的编程语言会建议接口的名称加上 I 前缀。
定义的变量比接口少了一些属性是不允许的,多一些属性也是不允许的。可见,赋值的时候,变量的形状必须和接口的形状保持一致。
可选属性的含义是该属性可以不存在。
一旦定义了任意属性,那么确定属性和可选属性的类型都必须是它的类型的子集。
一个接口中只能定义一个任意属性。如果接口中有多个类型属性,则可以在任意属性中使用联合属性 [propName : type] : any
只对属性的约束存在于第一次给对象赋值的时候,而不是第一次给只读属性赋值的时候。
interface IArguments { [index: number]: any; length: number; callee: Function; }
用any表示数组中允许出现的任类型
let list: any[] = ['xcatliu', 25, { website: 'http://xcatliu.com' }];
函数
两种常见的定义函数的方式:函数声明(Function Declaration)和函数表达式(Function Expression)。
注意:输入多余的(或者少于要求的)参数是不被允许的。
可选参数必须接在必须参数的后面。也就是说,可选参数后面不允许再出现必须参数。
ts会将添加了默认值的参数识别为可选参数,此时就不受「可选参数必须接在必须参数后面」的限制了。
剩余参数(...rest)只能是最后一个参数。
类型别名与字符串字面量类型都是使用type进行定义。
泛型
泛型(Generics)是指在定义函数、接口或者类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。
编译选项
选项 | 类型 | 默认值 | 描述 |
allowJs | boolean | false | 允许编译js文件 |
allowSyntheticDefaultImports | boolean | false | 允许对不包含默认导出的模块使用默认导出。这个选项不会影响生成的代码,只会影响类型检查 |