let suits = ["hearts", "spades", "clubs", "diamonds"];
function pickCard(x: {suit: string; card: number; }[]): number;
function pickCard(x: number): {suit: string; card: number; };
function pickCard(x): any {
// Check to see if we're working with an object/array
// if so, they gave us the deck and we'll pick the card
if (typeof x == "object") {
let pickedCard = Math.floor(Math.random() * x.length);
return pickedCard;
}
// Otherwise just let them pick the card
else if (typeof x == "number") {
let pickedSuit = Math.floor(x / 13);
return { suit: suits[pickedSuit], card: x % 13 };
}
}
let myDeck = [{ suit: "diamonds", card: 2 }, { suit: "spades", card: 10 }, { suit: "hearts", card: 4 }];
let pickedCard1 = myDeck[pickCard(myDeck)];
alert("card: " + pickedCard1.card + " of " + pickedCard1.suit);
let pickedCard2 = pickCard(15);
alert("card: " + pickedCard2.card + " of " + pickedCard2.suit);
介绍
Typescript 对代码进行了静态分析,排除一些类型错误,其是js的超集。TypeScript使用的是结构性类型系统。 当我们比较两种不同的类型时,并不在乎它们从何处而来,如果所有成员的类型都是兼容的,我们就认为它们的类型是兼容的。因此在使用时,只要牢记这条准则,就能帮组我们排除大多编译不通过问题!
基础类型
布尔值 boolean
数字类型 number 十进制、十六进制0x、八进制0o、二进制0b
字符串 string
数组 [],如number[]或Array
元组,如[string, number]
枚举,如
编译后
可见,枚举类型,是一个对象,其值为
通俗的理解,枚举类似于数学中的集合A={1,2,3},使用这个集合的时候,只能用集合里面的值1、2、3,集合之外的值不能使用,会报错
枚举还有一个特点是,我们可以通过值取键,可以通过键取值
undefined 和 null
任意值any,编程阶段不清楚的类型或者想绕过类型检查器的类型
空值void,常用于无返回值的函数,如
类型断言
类型断言,可以理解为类型转换,但js中的类型转换是在运行时进行转换的,而类型断言是ts在编译时进行转换的,它是一种人为的“主观意愿”的转换,告诉编译器它不应该报错,其是此类型的
看个例子
这个经过ts编译时,会报Error
而经过类型断言后,
编译器会强制把{},解析为Foo类型,即将{}转换为了Foo类型,从而绕过了编译器的编译机制。不再报错
接口
1、属性接口
保证两个类型内部结构兼容,则为实现接口,如
注:
即person必须拥有两个属性,name、age,多于其不限,少于不行!!!
hobby后跟?代表可选属性,预定义了属性hobby,不用对其赋值。函数中依旧可以用hobby,编译不报错。
readonly + 属性,代表其为只读属性,不能对其值进行变更
ReadonlyArray,把所有可变方法去掉,确保数组被创建后不会更改
以上例子定义了ro为不可改数组。对其做的变更都会被报error,如果需要强制对其更改,需采用类型断言
那么问题来了,何时使用readonly,何时使用const,最简单的判断是,若为变量,用const,若为属性用readonly
2、函数类型接口
举例如下:
其就像是一个只有参数列表和返回值类型的函数定义,其中对其参数名称不做检查,只检查其类型,即
参数类型一致、函数返回值一致。即为实现了函数类型接口。
如
3、可索引的类型接口
用于数组类如a[10]
或
对象类如ageMap["daniel"],具体如下4、类类型接口
强制类符合接口规则
5、继承接口
如下:
6、混合类型接口
有时我们希望一个对象,既可以当做对象又可以当做函数、并带有额外属性,此样子的接口定义如下:
7、接口继承类
当接口继承了一个类类型时,它会继承类的成员但不包括其实现。 就好像接口声明了所有类中存在的成员,但并没有提供具体实现一样。 接口同样会继承到类的private和protected成员。 这意味着当你创建了一个接口继承了一个拥有私有或受保护的成员的类时,这个接口类型只能被这个类或其子类所实现(implement)。
类
1、基本用法
经过tsc编译后的代码如下:
2、修饰符
public,类中成员默认为是public来做修饰。如上面所示例子的成员变量,均是public的
private,成员变量被标记为private时,它就不能在声明它的类的外部访问
编译为js后为
protected不能在外部调用但可以被继承
3、存取器
TypeScript支持通过getters/setters来截取对对象成员的访问。 它能帮助你有效的控制对对象成员的访问。
tsc转换后为
4、静态属性
tsc编译后
5、抽象类
抽象类做为其它派生类的基类使用。 它们一般不会直接被实例化。 不同于接口,抽象类可以包含成员的实现细节。
abstract
关键字是用于定义抽象类和在抽象类内部定义抽象方法。抽象类中的抽象方法不包含具体实现并且必须在派生类中实现。 抽象方法的语法与接口方法相似。 两者都是定义方法签名但不包含方法体。 然而,抽象方法必须包含
abstract
关键字并且可以包含访问修饰符。函数
this,不确定其值是,可定义为any类型,
重载是为同一个函数提供多个函数类型定义来进行函数重载。 编译器会根据这个列表去处理函数的调用。 在调用的时候进行正确的类型检查,为了让编译器能够选择正确的检查类型,它与JavaScript里的处理流程相似。 它查找重载列表,尝试使用第一个重载定义。 如果匹配的话就使用这个。 因此,在定义重载的时候,一定要把最精确的定义放在最前面。
function pickCard(x): any
并不是重载列表的一部分泛型