本文首发于 TS:TypeScript 简单入门
什么是 Typescript
TypeScript 是 JavaScript 的超集。它基于 JavaScript 的类型定义提供了一个更加强大,更加灵活类型系统。目前由微软进行维护和管理。
基本类型
-
布尔值
// 声明 let isDone: boolean isDone = true // OK isDone = typeof 1 === "number" // OK isDone = "" // Type 'string' is not assignable to type 'boolean'.
-
数字
// 声明 let index: number // 赋值 index = 10 // OK index = "10" // Type 'string' is not assignable to type 'number'.
-
字符串
let myFavoriteNumber: string color = "seven" // OK color = 7 // Type 'number' is not assignable to type 'string'.
-
数组
let numberList: number[] // 只能存放 number 类型元素的数组,等价于 let numberList: Array<number> numberList = [1, 2, 3] // OK numberList = [1, 2, 3, "4"] // Type 'string' is not assignable to type 'number'.
-
元组
元组也是数组,但是元组中的元素类型可以被指定多种。
let tuple: [string, number] tuple = ["hello", 10] // OK tuple = ["hello", 10, "world"] // Type 'string' is not assignable to type 'number'.
对象类型
对象是所有其他类型的超集,包括那些不可枚举的对象。要定义一个对象类型,只需列出它的属性及其类型即可,或者可以使用 object
。
let person: {
name: string
age: number
}
let obj: object
OK
person = {
name: "Tom",
age: 10,
}
obj = { 1: "1", a: { b: "b" }, c: [1, 2, 3] }
报错
person = {
name: "Tom",
age: "10",
} // Type 'string' is not assignable to type 'number'.
obj = 1 // Type 'number' is not assignable to type 'object'.
特殊类型(any、unknown、void、never)
-
any
当不想让一个特殊值导致 TypeScript 在类型检查时抛出错误,可以使用
any
。let notSure: any
OK
notSure = false // OK notSure = 1 // OK notSure = "maybe a string instead" // OK notSure("hello") // OK
-
unknown
类似于
any
类型,但不能作为函数执行。let notSure: unknown
OK
notSure = false // OK notSure = 1 // OK notSure = "maybe a string instead" // OK
报错
notSure("hello") // Object is of type 'unknown'. notSure.toFixed() // Property 'toFixed' does not exist on type 'unknown'.
-
void
函数没有返回值时,可以使用
void
。function warnUser(): void { console.log("This is my warning message") }
-
never
表示永远不存在的值的类型。当函数执行时抛出异常,或永远无法执行完毕,可以使用
never
。function error(message: string): never { throw new Error(message) } function infiniteLoop(): never { while (true) {} }
联合类型
联合类型(Union Types)表示取值类型可以为多种类型中的一种。
let myFavoriteNumber: string | number
myFavoriteNumber = "seven" // OK
myFavoriteNumber = 7 // OK
类型别名和接口
当类型的定义较为复杂时或者需要复用时,可以给类型设置一个别名(Type Aliases),或者使用接口(Interface)定义。
type Animal = {
name: string
}
const cat: Animal = { name: "Tom" }
等价于
interface Animal {
name: string
}
const cat: Animal = { name: "Tom" }
可以通过下面方式实现类型和接口的继承
type Bear = Animal & {
honey: boolean
}
interface Bear extends Animal {
honey: boolean
}
不过二者并不是完全相同的,类型别名不允许重复定义,而接口可以重复定义,并实现继承。
OK
interface Animal {
name: string
}
interface Animal {
age: number
}
const cat: Animal = { name: "Tom", age: 2 }
报错
type Animal = {
name: string
}
// Duplicate identifier 'Animal'.
type Animal = {
age: number
}
类型断言
有时候会遇到 TypeScript 无法识别的值类型信息,但你清楚知道它具有某种类型时,你可以用 as
操作符来进行类型断言。
let someValue: any = "this is a string"
let strLength: number = (someValue as string).length
或者使用尖括号语法(除非代码在.tsx 文件中),与 as
是等价的
let someValue: any = "this is a string"
let strLength: number = (<string>someValue).length
在函数中进行使用类型检查
-
指定参数的类型
function add(a: number, b: number) { return a + b } add(1, 2) // OK add("1", "2") // Error, 'string' is not assignable to 'number'
-
指定返回值的类型
function add(a: number, b: number): number { return a + b } let result: number = add(1, 2) // OK
-
指定可选参数的类型
function add(a: number, b?: number) { return a + (b || 0) } add(1) // OK add(1, 2) // OK add(1, "2") // Error, 'string' is not assignable to 'number'
-
指定剩余参数的类型
function add(a: number, ...rest: number[]) { return a + rest.reduce((p, n) => p + n, 0) } add(1) // OK add(1, 2, 3) // OK add(1, 2, "3") // Error, 'string' is not assignable to 'number'
-
指定参数默认值的类型(可以,但没必要)
function add(a: number = 0, b: number = 0) { return a + b } add() // OK add(1) // OK add(1, 2) // OK add(1, "2") // Error, 'string' is not assignable to 'number'
枚举
枚举是 TypeScript 对 JavaScript 语言运行时添加的一个特性。可以用来描述一组常量。
-
数字枚举
enum Color { Red, Green, Blue, }
等价于
const Color = { "0": "Red", "1": "Green", "2": "Blue", Red: 0, Green: 1, Blue: 2, }
作为类型使用
const c: Color = Color.Green
-
在数字枚举中设置初始值
上面代码中,我们看到了一个数字枚举,它的值是从 0 开始的。如果不想从 0 开始,可以使用如下方式来指定第一个值:
enum Color { Red = 1, Green, Blue, }
等价于
const Color = { "1": "Red", "2": "Green", "3": "Blue", Red: 1, Green: 2, Blue: 3, }
-
字符串枚举
与数字枚举的不同之处在于,在字符串枚举中,每个成员都必须用字符串或另一个字符串枚举成员初始化。
enum Direction { Up = "UP", Down = "DOWN", Left = "LEFT", Right = "RIGHT", }
等价于
const Direction = { Up: "UP", Down: "DOWN", Left: "LEFT", Right: "RIGHT" }
作为类型使用
const up: Direction = Direction.Up
-
使用示例
enum ShapeKind { Circle, Square, } interface Circle { kind: ShapeKind.Circle radius: number } interface Square { kind: ShapeKind.Square sideLength: number } let c: Circle = { kind: ShapeKind.Circle, radius: 100, } let s: Square = { kind: ShapeKind.Square, sideLength: 100, } function area(shape: Circle | Square): number { switch (shape.kind) { case ShapeKind.Circle: return Math.PI * shape.radius ** 2 case ShapeKind.Square: return shape.sideLength ** 2 } } area(c) // 314.1592653589793 area(s) // 10000
其他不常用类型
-
null
let n: null = null
-
undefined
let u: undefined = undefined
-
bigint
bigint 类型是 JavaScript 中的一个新的原始类型,它表示一个无符号整数,可以表示任意大小的整数。
let bigInt: bigint = 100n
-
symbol
symbol 类型是 JavaScript 中的一个新的原始类型,它表示一个独一无二的值。
let sym1: symbol = Symbol("key1") let sym2: symbol = Symbol("key1") sym1 === sym2 // false
如何将 TypeScript 编译为 JavaScript ?
- 单文件
-
全局安装 typescript
npm i -g typescript
-
使用 tsc 命令将 TypeScript 文件编译为 JavaScript。
tsc javascript.js
- Webpack 中使用
-
安装 typescript 和
ts-loader
npm i typescript ts-loader -D
-
在 webpack.config.js 中配置 ts-loader
module.exports = { module: { rules: [ { test: /\.tsx?$/, use: "ts-loader", exclude: /node_modules/, }, ], }, }
-
在根目录配置
tsconfig.json
,用于指定编译项目所需的根目录下的文件以及编译选项。{ "compilerOptions": { "module": "esnext", // 模块类型 "target": "es5", // 指定编译目标 "lib": ["esnext"] // 指定引入的库 }, "include": ["src/**/*"], // 指定编译的文件 "exclude": ["node_modules"] // 排除编译的文件 }
更多配置项参考:https://www.typescriptlang.org/docs/handbook/tsconfig-json.html
参考资料:
网友评论