TS:TypeScript 简单入门

本文首发于 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 ?

  • 单文件
  1. 全局安装 typescript

    npm i -g typescript
    
  2. 使用 tsc 命令将 TypeScript 文件编译为 JavaScript。

    tsc javascript.js
    
  • Webpack 中使用
  1. 安装 typescript 和 ts-loader

    npm i typescript ts-loader -D
    
  2. 在 webpack.config.js 中配置 ts-loader

    module.exports = {
      module: {
        rules: [
          {
            test: /\.tsx?$/,
            use: "ts-loader",
            exclude: /node_modules/,
          },
        ],
      },
    }
    
  3. 在根目录配置 tsconfig.json,用于指定编译项目所需的根目录下的文件以及编译选项。

    {
      "compilerOptions": {
        "module": "esnext", // 模块类型
        "target": "es5", // 指定编译目标
        "lib": ["esnext"] // 指定引入的库
      },
      "include": ["src/**/*"], // 指定编译的文件
      "exclude": ["node_modules"] // 排除编译的文件
    }
    

    更多配置项参考:https://www.typescriptlang.org/docs/handbook/tsconfig-json.html


参考资料:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,142评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,298评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,068评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,081评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,099评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,071评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,990评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,832评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,274评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,488评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,649评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,378评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,979评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,625评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,643评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,545评论 2 352