TypeScript——基础语法

10,882次阅读
没有评论

共计 7782 个字符,预计需要花费 20 分钟才能阅读完成。

认识 TypeScript

        TypeScript 是拥有类型的 JavaScript 超集,它可以编译成普通、干净、完整的 JavaScript 代码。

TypeScript 的编译环境

        TypeScript 最终会被编译成 JavaScript 来运行,所以我们需要搭建对应的环境。我们需要在电脑上安装 TypeScript,这样就可以通过 TypeScript 的 Compiler 将其编译成 JavaScript。

# 安装命令
npm install typescript -g
# 查看版本
tsc --version
# 编译 TS 文件
tsc ./index.ts

TypeScript 的运行环境

  1. 通过 tsc 编译 TypeScript 到 JavaScript 代码,在浏览器或者 Node 环境下运行 JavaScript 代码;
  2. 通过 webpack,配置本地的 TypeScript 编译环境和开启一个本地服务,可以直接运行在浏览器上;
  3. 通过 ts-node 库,为 TypeScript 的运行提供执行环境;

 使用 ts-node

# 安装 ts-node
npm install ts-node -g
# 另外 ts-node 需要依赖 tslib 和 @types/node 两个包
npm install tslib @types/node -g
# 通过 ts-node 来运行 TypeScript 的代码
ts-node index.ts

tip:安装 ts-node 后,可以使用 nodemon 直接运行 TS 文件。

变量的声明

        声明了类型后 TypeScript 就会进行类型检测,声明的类型可以称之为类型注解(Type Annotation)。完整的声明格式如下:var/let/const 标识符: 数据类型 = 赋值;

JavaScript 和 TypeScript 的数据类型

TypeScript——基础语法

JavaScript 类型 – number 类型

         数字类型是我们开发中经常使用的类型,TypeScript 和 JavaScript 一样,不区分整数类型(int)和浮点型(double),统一为 number 类型。

        ES6 新增了二进制和八进制的表示方法,而 TypeScript 也是支持二进制、八进制、十六进制的表示:

let num: number
num = 100 // 十进制
num = 0b110 // 二进制
num = 0o555 // 八进制
num = 0xf23 // 十六进制
JavaScript 类型 – boolean 类型

        boolean 类型只有两个取值:true 和 false。

JavaScript 类型 – string 类型

        string 类型是字符串类型,可以使用单引号或者双引号表示,同时也支持 ES6 的模板字符串来拼接变量和字符串。

JavaScript 类型 – Array 类型
const list: string[] = ['aaa', 'bbb']
const list: Array = ['ccc', 'ddd']
JavaScript 类型 – Object 类型

        object 对象类型可以用于描述一个对象,如下写法,object 表示一个通用的对象,这个时候我们不能从 info 中获取数据,也不能设置数据。这种写法不推荐。

const info: object = {name: 'heart'}
console.log(info.name) // 错误
info.name = '小王' // 错误
JavaScript 类型 – Symbol 类型

        在 ES5 中,如果我们是不可以在对象中添加相同的属性名称的,比如下面的做法:

const persion = {
    name: '小王',
    name: '老王'
}

        通常我们的做法是定义两个不同的属性名字,比如 name1,name2。但是我们也可以通过 symbol 来定义相同的名称,因为 Symbol 函数返回的是不同的值:

const s1: symbol = Symbol('name')
const s2: symbol = Symbol('name')
const person = {[s1]: '小王',
    [s2]: '老王',
}
JavaScript 类型 – null 和 undefined 类型

        在 JavaScript 中,undefined 和 null 是两个基本数据类型,在 TypeScript 中,它们各自的类型也是 undefined 和 null,也就意味着它们既是实际的值,也是自己的类型。

JavaScript 类型 –函数
参数的类型注解

        声明函数时,可以在每个参数后添加类型注解,以声明函数接受的参数类型。

函数的返回值类型

        注解在函数列表的后面,和变量的类型注解一样,我们通常情况下不需要返回类型注解,因为 TypeScript 会根据 return 返回值推断函数的返回类型。

匿名函数的参数

TypeScript——基础语法

对象类型
TypeScript——基础语法 可选类型

        对象类型也可以指定哪些属性是可选的,可以在属性的后面添加一个?。

TypeScript 类型 – any 类型

        在某些情况下,我们确实无法确定一个变量的类型,并且可能它会发生一些变化,这个时候我们可以使用 any 类型(类似于 Dart 语言中的 dynamic 类型)

  • 我们可以对 any 类型的变量进行任何的操作,包括获取不存在的属性、方法;
  • 我们给一个 any 类型的变量赋值任何的值,比如数字、字符串的值;
TypeScript 类型 – unknown 类型 

        unknown 是 TypeScript 中比较特殊的一种类型,它用于描述类型不确定的变量。和 any 类型有点类似,但是unknown 类型的值上做任何事情都是不合法的。因此,unknown 在进行任何操作的时候,都需要进行类型校验(缩小),才能根据具体的类型操作

let foo: unknown = 'aaa'
foo = 123 // 合法,unknown 可以是任何类型
console.log(foo.length) // 不合法,unknown 进行操作时,需要进行类型缩小
if(typeof foo === 'string') {console.log(foo.length) // 合法,类型缩小后,类型确定了
}

TypeScript——基础语法

 TypeScript 类型 – void 类型

        void 通常用来指定一个函数是没有返回值的,那么它的返回值就是 void 类型,我们也可以显示的来指定返回值是 void。

tip:我们可以将 undefined 赋值给 void 类型,也就是函数可以返回 undefined

// 应用场景:用来定义函数的类型
type FooType = () => viod
const foo: FooType = () => {}
TypeScript 类型 – never 类型

TypeScript——基础语法

 TypeScript 类型 – tuple 类型

        tuple 和数组区别:

  1. 数组中通常建议存放相同类型的元素,不同类型的元素是不推荐放在数组中。(可以放在对象或者元组中);
  2. 元组中每个元素都有自己特性的类型,根据索引值获取到的值可以确定对应的类型。
const info: [string, number, number] = ['heart', 18, 1.88]

TypeScript——基础语法

 TypeScript 语法细节

联合类型

TypeScript——基础语法

 TypeScript——基础语法

 类型别名

TypeScript——基础语法

接口的声明

TypeScript——基础语法

 interface 和 type 区别

TypeScript——基础语法

 交叉类型

TypeScript——基础语法

// 交叉类型: 两种 (多种) 类型要同时满足
type NewType = number & string // 没有意义

// 应用场景
interface IKun {
  name: string
  age: number
}

interface ICoder {
  name: string
  coding: () => void
}

type InfoType = IKun & ICoder

const info: InfoType = {
  name: "why",
  age: 18,
  coding: function() {console.log("coding")
  }
}

类型断言 as

        TypeScript 只允许类型断言转换为 更具体 或者 不太具体 的类型版本,此规则可防止不可能的强制转换 

TypeScript——基础语法

非空类型断言!

TypeScript——基础语法

字面量类型

TypeScript——基础语法TypeScript——基础语法  

类型缩小

  • typeof
  • 平等缩小(比如 ===、!==)
  • instanceof
  • in 
// 1.typeof: 使用的最多
function printID(id: number | string) {if (typeof id === "string") {console.log(id.length, id.split(" "))
  } else {console.log(id)
  }
}

// 2.===/!==: 方向的类型判断
type Direction = "left" | "right" | "up" | "down"
function switchDirection(direction: Direction) {if (direction === "left") {console.log("左:", "角色向左移动")
  } else if (direction === "right") {console.log("右:", "角色向右移动")
  } else if (direction === "up") {console.log("上:", "角色向上移动")
  } else if (direction === "down") {console.log("下:", "角色向下移动")
  }
}

// 3. instanceof: 传入一个日期, 打印日期
function printDate(date: string | Date) {if (date instanceof Date) {console.log(date.getTime())
  } else {console.log(date)
  }
}

// 4.in: 判断是否有某一个属性
interface ISwim {swim: () => void
}

interface IRun {run: () => void
}

function move(animal: ISwim | IRun) {if ("swim" in animal) {animal.swim()
  } else if ("run" in animal) {animal.run()
  }
}

 TypeScript 函数类型

         在 JavaScript 开发中,函数是重要的组成部分,并且函数可以作为一等公民(可以作为参数,也可以作为返回值进行传递)。我们可以编写 函数类型的表达式(Function Type Expressions),来表示函数类型。

TypeScript——基础语法

调用签名(Call Signatures)
TypeScript——基础语法构造签名(Construct Signatures)

TypeScript——基础语法

 参数的可选类型

TypeScript——基础语法

 默认参数

TypeScript——基础语法

 剩余参数

        从 ES6 开始,JavaScript 也支持剩余参数,剩余参数语法允许我们将一个不定数量的参数放到一个数组中。

函数的重载

        在 TypeScript 中,我们可以去编写不同的重载签名(overload signatures)来表示函数可以以不同的方式进行调用;一般是编写两个或者以上的重载签名,再去编写一个通用的函数以及实现。

TypeScript——基础语法

 tip:如果需求可以通过联合类型或重载来实现,尽量选择联合类型实现

This
可推导的 this 类型

TypeScript——基础语法

this 的编译选项
TypeScript——基础语法
 指定 this 的类型

TypeScript——基础语法

 this 相关的内置工具

TypeScript——基础语法

 this 相关的内置工具 – ThisType

TypeScript——基础语法

TypeScript 面向对象

认识类的使用

类的定义

TypeScript——基础语法

类的继承 

TypeScript——基础语法

类的成员修饰符
        在 TypeScript 中,类的属性和方法支持三种修饰符:public、private、protected。public 是默认的修饰符。
  • public 修饰的是在任何地方可见、公有的属性或方法,默认编写的属性就是 public 的;
  • private 修饰的是仅在同一类中可见、私有的属性或方法;
  • protected 修饰的是仅在类自身及子类中可见、受保护的属性或方法;
只读属性 readonly
        如果有一个属性我们不希望外界可以任意的修改,只希望确定值后直接使用,那么可以使用 readonly。
getters/setters

        在前面一些私有属性我们是不能直接访问的,或者某些属性我们想要监听它的获取 (getter) 和设置 (setter) 的过程,这个时候我们 可以使用存取器。

class Person {
  // 私有属性: 属性前面会使用_
  private _name: string
  private _age: number

  constructor(name: string, age: number) {this._name = name}

  // setter/getter: 对属性的访问进行拦截操作
  set name(newValue: string) {this._name = newValue}

  get name() {return this._name}
}
const p = new Person("why", 100)
p.name = "kobe"
console.log(p.name)
参数属性(Parameter Properties)

TypeScript——基础语法

 抽象类 abstract

TypeScript——基础语法

 TypeScript——基础语法

 类的类型

        类本身也是可以作为一种数据类型的。下面代码没有报错的原因是:typeScript 对于类型检测的时候使用的鸭子类型。

// TypeScript 对于类型检测的时候使用的鸭子类型
// 鸭子类型: 如果一只鸟, 走起来像鸭子, 游起来像鸭子, 看起来像鸭子, 那么你可以认为它就是一只鸭子
// 鸭子类型, 只关心属性和行为, 不关心你具体是不是对应的类型

class Person {constructor(public name: string, public age: number) {}

  running() {}
}

class Dog {constructor(public name: string, public age: number) {}
  running() {}
}

function printPerson(p: Person) {console.log(p.name, p.age)
}

printPerson(new Person("why", 18))
printPerson({name: "kobe", age: 30, running: function() {}})
printPerson(new Dog("旺财", 3))
const person: Person = new Dog("果汁", 5)

对象类型的属性修饰符(Property Modifiers)

TypeScript——基础语法

 索引签名(Index Signatures)

TypeScript——基础语法

// 索引签名的基本使用

// 案例 1
interface InfoType {
  // 索引签名: 可以通过字符串索引, 去获取到一个值, 也是字符串
  [key: string]: string
}
function getInfo(): InfoType {}
const info = getInfo()
console.log(info["name"], info.age, info.address)

// 案例 2
interface ICollection {[index: number]: string
  length: number
}

function printCollection(collection: ICollection) {for (let i = 0; i 

// 索引签名的类型问题

interface IIndexType {
  // 返回值类型的目的是告知通过索引去获取到的值是什么类型
  // [index: number]: string
  // [index: string]: any
  [index: string]: string
}

// 索引签名: [index: number]: string
const names: IIndexType = ["abc", "cba", "nba"]

// 索引签名: [index: string]: any: 没有报错
// 1. 索引要求必须是字符串类型 names[0] => names["0"]
const names: IIndexType = ["abc", "cba", "nba"]

// 索引签名: [index: string]: string: 会报错
// 严格字面量赋值检测: ["abc", "cba", "nba"] => Array 实例 => names[0] names.forEach
const names: IIndexType = ["abc", "cba", "nba"]
// names["forEach/map/filter"] => function,并非 string,所以报错

// 两个索引类型的写法

interface IIndexType {[index: number]: string
  [key: string]: any

  // 要求一: 下面的写法不允许: 数字类型索引的类型, 必须是字符串类型索引的类型的 子类型
  // 结论: 数字类型必须是比如字符串类型更加确定的类型(需要是字符串类型的子类型)
  // 原因: 所有的数字类型都是会转成字符串类型去对象中获取内容
  // 数字 0: number|string, 当我们是一个数字的时候, 既要满足通过 number 去拿到的内容, 不会和            
  // string 拿到的结果矛盾

  // 要求二: 如果索引签名中有定义其他属性, 其他属性返回的类型, 必须符合 string 类型返回的属性
  // [index: number]: string
  // [key: string]: number|string

  // aaa: string
  // bbb: boolean 错误的类型
}

const names: IIndexType = ["abc", "cba", "nba"]
const item1 = names[0]
const forEachFn = names["forEach"]

names["aaa"]

接口继承

TypeScript——基础语法 接口的实现

TypeScript——基础语法

 抽象类和接口的区别

TypeScript——基础语法

 严格的字面量赋值检测

TypeScript——基础语法

TypeScript——基础语法

interface IPerson {
  name: string
  age: number
}

// 1. 奇怪的现象一: 
// 定义 info, 类型是 IPerson 类型
const obj = {
  name: "why",
  age: 18,
  height: 1.88 // 多了一个 height 属性
}
const info: IPerson = {name: "why", age: 18, height: 1.88} // 报错
const info: IPerson = obj // 不报错

// 2. 奇怪的现象二:
function printPerson(person: IPerson) {}
const kobe = {name: "kobe", age: 30, height: 1.98}
printPerson({name: "why", age: 18, height: 1.88}) // 报错
printPerson(kobe) // 不报错

// 解释现象
// 第一次创建的对象字面量, 称之为 fresh(新鲜的)
// 对于新鲜的字面量, 会进行严格的类型检测. 必须完全满足类型的要求(不能有多余的属性)

 TypeScript 枚举类型

        枚举类型是为数不多的 TypeScript 特性有的特性之一:

  • 枚举其实就是将一组可能出现的值,一个个列举出来,定义在一个类型中,这个类型就是枚举类型;
  • 枚举允许开发者定义一组命名常量,常量可以是数字、字符串类型。

 TypeScript——基础语法

// 定义枚举类型
enum Direction {
   LEFT = 0,
   RIGHT = 1
 }

enum Direction {
   LEFT = 100,
   RIGHT
}

enum Direction {
  LEFT = "LEFT",
  RIGHT = "RIGHT"
}

enum Operation {Read = 1 

原文地址: TypeScript——基础语法

    正文完
     0
    Yojack
    版权声明:本篇文章由 Yojack 于2024-11-10发表,共计7782字。
    转载说明:
    1 本网站名称:优杰开发笔记
    2 本站永久网址:https://yojack.cn
    3 本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长进行删除处理。
    4 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
    5 本站所有内容均可转载及分享, 但请注明出处
    6 我们始终尊重原创作者的版权,所有文章在发布时,均尽可能注明出处与作者。
    7 站长邮箱:laylwenl@gmail.com
    评论(没有评论)