简介
- TypeScript 是JavaScript 的超集,对js提供了类型标注,使得静态推断成为可能,让一些错误在运行之前就可以被诊断出来。
- TypeScript 可以编译出纯净、 简洁的 JavaScript 代码,并且可以运行在任何浏览器上、Node.js 环境中和任何支持 ECMAScript 3(或更高版本)的JavaScript 引擎中。
安装
// 全局安装
npm install -g typescript
// 查看版本号
tsc -V
编译代码
// 使用ts编译xxx.ts文件,将生成xxx.js
tsc xxx.ts
基础类型
- TypeScript 支持与 JavaScript 几乎相同的数据类型,此外还提供了实用的枚举类型方便我们使用。
布尔值
- 最基本的数据类型就是简单的 true/false 值,在JavaScript 和 TypeScript 里叫做 boolean(其它语言中也一样)。
let isDone: boolean = false
数字
- 数字类型是 number。 除了支持十进制和十六进制字面量,TypeScript 还支持 ECMAScript 2015中引入的二进制和八进制字面量。
let decLiteral: number = 20
let hexLiteral: number = 0x14
let binaryLiteral: number = 0b10100
let octalLiteral: number = 0o24
字符串
let name: string = 'bob'
name = 'smith'
数组
- 有两种方式可以定义数组。 第一种,可以在元素类型后面接上 [],表示由此类型元素组成的一个数组:
let list: number[] = [1, 2, 3]
- 第二种方式是使用数组泛型,Array<元素类型>:
let list: Array<number> = [1, 2, 3]
元组
- 元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。
let x: [string, number]
x = ['hello', 10] // OK
x = [10, 'hello'] // Error
注意:自从 TypeScript 3.1 版本之后,访问越界元素会报错
枚举
- enum 类型是对 JavaScript 标准数据类型的一个补充。 像 C# 等其它语言一样,使用枚举类型可以为一组数值赋予友好的名字。
enum Color {
Red, Green, Blue}
let c: Color = Color.Green
- 默认情况下,从 0 开始为元素编号。 你也可以手动的指定成员的数值。 例如,我们将上面的例子改成从 1 开始编号:
enum Color {
Red = 1, Green, Blue}
let c: Color = Color.Green
- 枚举类型提供的一个便利是你可以由枚举的值得到它的名字。 例如,我们知道数值为 2,但是不确定它映射到 Color 里的哪个名字,我们可以查找相应的名字:
enum Color {
Red = 1, Green, Blue}
let colorName: string = Color[2]
console.log(colorName) // 显示'Green'因为上面代码里它的值是2
any
- 有时候,我们会想要为那些在编程阶段还不清楚类型的变量指定一个类型。那么我们可以使用 any 类型来标记这些变量:
let notSure: any = 4
notSure = 'maybe a string instead'
notSure = false // 也可以是个 boolean
void
- 某种程度上来说,void 类型像是与 any 类型相反,它表示没有任何类型。 当一个函数没有返回值时,你通常会见到其返回值类型是 void
function warnUser(): void {
console.log('This is my warning message')
}
- 声明一个 void 类型的变量没有什么大用,因为你只能为它赋予 undefined 和 null
let unusable: void = undefined
null 和 undefined
- TypeScript 里,undefined 和 null 两者各自有自己的类型分别叫做 undefined 和 null。 和 void 相似,它们的本身的类型用处不是很大:
let u: undefined = undefined
let n: null = null
默认情况下 null 和 undefined 是所有类型的子类型。 就是说你可以把 null 和 undefined 赋值给 number 类型的变量。
然而,当你指定了 --strictNullChecks 标记,null 和 undefined 只能赋值给 void 和它们各自,这能避免 很多常见的问题。 也许在某处你想传入一个 string 或 null 或 undefined,你可以使用联合类型 string | null | undefined
never
- never 类型表示的是那些永不存在的值的类型。
// 返回never的函数必须存在无法达到的终点
function error(message: string): never {
throw new Error(message)
}
// 推断的返回值类型为never
function fail() {
return error("Something failed")
}
// 返回never的函数必须存在无法达到的终点
function infiniteLoop(): never {
while (true) {
}
}
object
- object 表示非原始类型,也就是除 number,string,boolean,symbol,null或undefined 之外的类型。
declare function create(o: object | null): void
create({
prop: 0 }) // OK
create(null) // OK
create(42) // Error
create('string') // Error
create(false) // Error
create(undefined) // Error
类型断言
- 类型断言好比其它语言里的类型转换,但是不进行特殊的数据检查和解构。
- 类型断言有两种形式。 其一是“尖括号”语法:
let someValue: any = 'this is a string'
let strLength: number = (<string>someValue).length
- 另一个为
as
语法:
let someValue: any = 'this is a string'
let strLength: number = (someValue as string).length
两种形式是等价的。 至于使用哪个大多数情况下是凭个人喜好;然而,当你在 TypeScript 里使用 JSX 时,只有 as 语法断言是被允许的。
接口
- 接口用来描述一个结构
接口初探
interface LabelledValue {
label: string
}
function printLabel(labelledObj: LabelledValue) {
console.log(labelledObj.label)
}
let myObj = {
size: 10, label: 'Size 10 Object'}
printLabel(myObj)
可选属性
- 接口里的属性不全都是必需的。 有些是只在某些条件下存在,或者根本不存在。
- 带有可选属性的接口与普通的接口定义差不多,只是在可选属性名字定义的后面加一个 ? 符号。
interface SquareConfig {
color?: string;
width?: number;
}
function createSquare (config: SquareConfig): Square {
...
}
let mySquare = createSquare({
color: 'black'})
只读属性
- 一些对象属性只能在对象刚刚创建的时候修改其值。 你可以在属性名前用 readonly 来指定只读属性
interface Point {
readonly x: number
readonly y: number
}
- TypeScript 具有 ReadonlyArray 类型,它与 Array 相似,只是把所有可变方法去掉了,因此可以确保数组创建后再也不能被修改:
let a: number[] = [1, 2, 3, 4]
let ro: ReadonlyArray<number> = a
ro[0] = 12 // error!
ro.push(5) // error!
ro.length = 100 // error!
a = ro // error!
- 最简单判断该用 readonly 还是 const 的方法是看要把它做为变量使用还是做为一个属性。 做为变量使用的话用 const,若做为属性则使用 readonly。
函数类型
- 接口能够描述 JavaScript 中对象拥有的各种各样的外形。 除了描述带有属性的普通对象外,接口也可以描述函数类型。
interface SearchFunc {
(source: string, subString: string): boolean
}
- 对于函数类型的类型检查来说,函数的参数名不需要与接口里定义的名字相匹配。
let mySearch: SearchFunc
mySearch = function(src: string, sub: string): boolean {
let result = src.search(sub);
return result > -1
}
可索引的类型
- 我们也可以描述那些能够“通过索引得到”的类型,比如 a[10] 或 ageMap[‘daniel’]。
interface StringArray {
[index: number]: string
}
let myArray: StringArray
myArray = ['Bob', 'Fred']
let myStr: string = myArray[0]
- TypeScript 支持两种索引签名:字符串和数字。 可以同时使用两种类型的索引,但是数字索引的返回值必须是字符串索引返回值类型的子类型。 这是因为当使用
number
来索引时,JavaScript 会将它转换成string
然后再去索引对象。 也就是说用 100(一个number
)去索引等同于使用’100’(一个string
)去索引,因此两者需要保持一致。
class Animal {
name: string
}
class Dog extends Animal {
breed: string
}
// 错误:使用数值型的字符串索引,有时会得到完全不同的Animal!
interface NotOkay {
[x: number]: Animal
[x: string]: Dog
}
- 你可以将索引签名设置为只读,这样就防止了给索引赋值:
interface ReadonlyStringArray {
readonly [index: number]: string;
}
let myArray: ReadonlyStringArray = ['Alice', 'Bob'