TS基础

发布于 2023-03-16  33 次阅读


什么是 TypeScript

TypeScript 是一种由微软开发并开源的跨平台编程语言,最初开发 TypeScript 的目的是为了更好地开发大型项目,其作者为大名鼎鼎的 C# 之父 Anders Hejlsberg 。

TypeScript 存在的意义

TypeScript弥补了JS许多的不足,同时保留了JS的灵活性,大大提高了项目的开发效率以及可维护性。TypeScript 让 JavaScript变得更好

TypeScript 带来了什么改变

TypeScript 对代码自动补全,智能提示,所有函数变量可快速跳转到定义,具有更好的可维护性

TypeScript 的特点

1.静态类型检查让 TS 成为强类型语言2.TS 在支持与 JS 几乎相同的原始类型之外,还额外提供了枚举(Enum)和元组(Tuple)的支持

修饰符和静态关键字

  1. 访问修饰符:public private protected
  2. 静态关键字:static 定义全局唯一的静态变量和静态函数。
  3. 抽象关键字:abstract
  4. 只读关键字:readonly

接口

接口(interface)用于一系列成员的声明,但不包含实现,接口支持合并(重复声明),也可以继承于另一接口

联合类型

使用联合类型(Union Types)允许你在声明变量或接收参数时兼容多种类型。

泛型

使用泛型可以让一个类/函数支持多种类型的数据,使用时可以传入需要的类型。

命名空间

命名空间(namespace)用来定义标识符的可用范围,主要用于解决重名的问题,对于项目模块化有很大的帮助。Cocos Creator 中的 cc 就是一个内置的命名空间。

使用

原始数据类型和内置标准库

// 原始数据类型

const a: string = 'foobar'

const b: number = 100 // NaN Infinity

const c: boolean = true // false

// 在非严格模式(strictNullChecks)下,
// string, number, boolean 都可以为空
// const d: string = null
// const d: number = null
// const d: boolean = null

const e: void = undefined

const f: null = null

const g: undefined = undefined

// Symbol 是 ES2015 标准中定义的成员,
// 使用它的前提是必须确保有对应的 ES2015 标准库引用
// 也就是 tsconfig.json 中的 lib 选项必须包含 ES2015
const h: symbol = Symbol()

// Promise

// const error: string = 100

作用域问题

// 作用域问题

// 默认文件中的成员会作为全局成员
// 多个文件中有相同成员就会出现冲突
// const a = 123

// 解决办法1: IIFE 提供独立作用域
// (function () {
//   const a = 123
// })()

// 解决办法2: 在当前文件使用 export,也就是把当前文件变成一个模块
// 模块有单独的作用域
const a = 123

export {}

Object 类型

// Object 类型

export {} // 确保跟其它示例没有成员冲突

// object 类型是指除了原始类型以外的其它类型
const foo: object = function () {} // [] // {}

// 如果需要明确限制对象类型,则应该使用这种类型对象字面量的语法,或者是「接口」
const obj: { foo: number, bar: string } = { foo: 123, bar: 'string' }

数组类型

// 数组类型

export {} // 确保跟其它示例没有成员冲突

// 数组类型的两种表示方式

const arr1: Array<number> = [1, 2, 3]

const arr2: number[] = [1, 2, 3]

// 案例 -----------------------

// 如果是 JS,需要判断是不是每个成员都是数字
// 使用 TS,类型有保障,不用添加类型判断
function sum (...args: number[]) {
  return args.reduce((prev, current) => prev + current, 0)
}

枚举类型

标准枚举类型

// 标准的数字枚举
enum PostStatus {
  Draft = 0,
  Unpublished = 1,
  Published = 2
}

数字枚举,枚举值自动基于前一个值自增

enum PostStatus {
  Draft = 6,
  Unpublished, // => 7
  Published // => 8
}

字符串枚举

enum PostStatus {
  Draft = 'aaa',
  Unpublished = 'bbb',
  Published = 'ccc'
}

一般的枚举会侵入代码,编译之后声明双向键值对对象

// 标准的数字枚举
var PostStatus;
(function (PostStatus) {
    PostStatus[PostStatus["Draft"] = 0] = "Draft";
    PostStatus[PostStatus["Unpublished"] = 1] = "Unpublished";
    PostStatus[PostStatus["Published"] = 2] = "Published";
})(PostStatus || (PostStatus = {}));

所以建议使用常量枚举,不会侵入编译结果

const enum PostStatus {
  Draft,
  Unpublished,
  Published
}

编译后结果为,仅在后面编译为注释

// 枚举(Enum)
Object.defineProperty(exports, "__esModule", { value: true });
var post = {
    title: 'Hello TypeScript',
    content: 'TypeScript is a typed superset of JavaScript.',
    status: 0 /* Draft */ // 3 // 1 // 0
};

函数类型约束

标准约束 可选参数在参数后加?(a?:number)默认参数加=号,剩余参数如代码 所示

function func1 (a: number, b: number = 10, ...rest: number[]): string {
  return 'func1'
}

函数表达式定义函数 接收函数的变量应该也是有约束的

const func2: (a: number, b: number) => string = function (a: number, b: number): string {
  return 'func2'
}

任意类型

// 任意类型(弱类型)

export {} // 确保跟其它示例没有成员冲突

function stringify (value: any) {
  return JSON.stringify(value)
}

stringify('string')

stringify(100)

stringify(true)

let foo: any = 'string'

foo = 100

foo.bar()

// any 类型是不安全的

隐式类型推断

声明一个变量并赋值,会将变量隐式推断为赋值的类型

如果只声明变量不赋值,会隐式推断为any类型

export {} // 确保跟其它示例没有成员冲突

let age = 18 // number

// age = 'string'

let foo

foo = 100

foo = 'string'

// 建议为每个变量添加明确的类型标注

类型断言

在某些特定情况下,typescript不能推断出一个变量的具体类型,我们开发者根据逻辑知道变量的具体类型

export {} // 确保跟其它示例没有成员冲突

// 假定这个 nums 来自一个明确的接口
const nums = [110, 120, 119, 112]

const res = nums.find(i => i > 0)

// const square = res * res

const num1 = res as number

const num2 = <number>res // JSX 下不能使用
最后更新于 2023-07-20