👨‍💻
Hong's 前端笔记
  • 🌈About
  • JavaScript
    • 作用域
    • 闭包
    • this
      • bind()
    • 原型
      • Object.create()
      • 模拟“类”
      • ES6 Class
      • Function
    • 对象
    • 类型 & 值
      • 原生函数
      • 数组
      • 字符串
    • 异步
    • JavaScript 相关概念
      • Event Loop 事件循环
      • Prototype 原型
      • Context 执行上下文
      • this
      • Promise
    • JavaScript 常见问题
      • 手写实现
      • 看代码输出
  • React
    • 核心概念
    • 深入理解
      • State
      • 如何管理 State
      • React 渲染过程
      • 处理 DOM 事件
      • Pure 组件
      • Context
      • Key 属性
      • React.lazy()
      • Render Props
    • Hooks
      • useState
      • useRef
      • useEffect
        • Some details
      • 相关概念
      • 自定义 Hook
      • useEffect vs useLayoutEffect
    • React 相关问题
      • Class vs Function
  • React Libraries
    • Redux
      • Quick Start
      • 如何持久化 Redux 数据
      • 异步操作
      • 性能优化
      • Dive into immutability
    • Route v6
      • Quick Start
  • Reactivity
    • Immer
  • Vue
    • 深入理解
      • Composition vs Options
      • Reactivity
  • Network
    • Cookies
    • HTTP
    • HTTPS
    • CORS 跨域资源共享
    • 认证手段
    • 安全相关
    • 网络相关知识
  • Browser
    • DOM 操作
    • Events 事件
    • XHR & Fetch
    • 性能优化
    • HTML 相关概念
    • 浏览器相关概念
  • CSS
    • 盒模型
    • Layout 布局
    • Styles 样式
    • CSS 相关概念
    • CSS 相关技巧
      • 移动端适配
      • Flex
      • 动画
  • TypeScript
    • Quick Peek
    • Types in TypeScript
    • Narrowing
    • Functions in TypeScript
  • Workflow
    • Webpack
      • Webpack 概念
      • 资源管理
      • 管理输出
      • 开发环境配置
      • 生产环境配置
      • 优化代码运行性能
  • Others
    • 小程序与原生 Web 的区别
  • SSO
    • About
    • API Doc
    • 接入指南
Powered by GitBook
On this page
  • Object Types
  • Union Types
  • type 关键字
  • interface 关键字
  • type aliases 和 interface 的区别
  • interface 增加属性
  • type 增加属性
  • type 断言
  • 字面量 type
  • null & undefined
  • strictNullChecks off
  • strictNullChecks on
  • ! 断言
  • Enums 枚举类型
Edit on GitHub
  1. TypeScript

Types in TypeScript

Object Types

在函数声明时,可以指定传入 object 的类型

function foo (obj: { x: number, y: number }){
  ...
}

指定其中某些参数是 optional 的

function foo (obj: { x: number, y?: number }){
  ...
}
// both ok
foo({x: 1, y: 1})
foo({x: 1})

不过,如果某一参数是 optional 的,那么就应该在函数体内部对它进行判空

function foo (obj: { x: number, y?: number }){
  if(obj.y !== undefined){
    ...
  }
}

Union Types

可以由多个现有的 type 构建新的 type

function foo(id: number | string) {...}

foo(1)		// allowed
foo(true) // not allowed

foo接受的 id 就是一个 union type ,他可以是一个 number 或者 string

与上面的 optional 类似,如果在函数中定义了一个参数为 unino type,那么在函数体内可能需要 narrowing

function foo(id: number | string) {
  // not allowed,因为 id 可能是 number,number 没有 toUpperCase() 属性
  id.toUpperCase()
  // narrowing,allowed
  if(typeof id === 'string')
    id.toUpperCase()
}

type 关键字

类似于其他语言的 typedefine,可以将上述的 Object Types、Union Types 定义成一个新的”类型“

type Point = {
  x: number,
  y: number
}
type ID = number | string

// useage
function foo(point: Point)
function foo(id: ID)

注意的是,type 定义的新类型其实就是一个“别名” (type aliases)

如 type NewString = string,本质上 NewString 就是 string 类型,它们不是两个不同的类型

interface 关键字

interfaces 关键字是另一种给 Object Types 定义”类型“的方式

interface Point = {
  x: number,
  y: number
}

type aliases 和 interface 的区别

两者在大部分情况下没有区别,可以随意选择使用。

在多数情况下,可以按照自己的偏好选择 type 或者 interface,不过有一个不错的策略是:

尽量使用 interface,除非必须使用 type 的时候

关键的区别就是:interfaces是可以以增加新的属性的

interface Animal {
  name: string
}
// interface 创建后可以继续添加属性
interface Animal {
  age: number
}

const cat: Animal
cat.name = 'xxx'
cat.age = 1
type Animal = {
  name: string
}
// type 创建后就不能修改
type Aniaml = {
  age: number
}

interface 增加属性

interface Animal {
  name: string
}
interface Bear extends Animal {
  honey: boolean
}

const bear = getBear() 
bear.name
bear.honey

type 增加属性

type Animal = {
  name: string
}
type Bear = Animal & { 
  honey: boolean 
}

const bear = getBear();
bear.name;
bear.honey;

type 断言

有时候,你能确定一个值的类型,那么就可以使用断言,例如你确定 id 为 'main_canvas' 的 DOM 元素一定是 HTMLCanvasElement 类型

const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement

另一种用<>的写法

const myCanvas = <HTMLCanvasElement>document.getElementById("main_canvas")

类型断言在编译后会被移除,所以不必担心会出现 runtime 时问题

断言只能缩小或者扩大某一个类型,如下面的例子是不合法的

const foo = 'bar' as number		// not allowed

但是上述这一个限制有时候也有点太妨碍了,可以用下面的方法来解决

const foo = (bar as any) as T		// 先转为 any 再转为想要的类型

字面量 type

在 Typescript 中,下面两种写法是等价的

const foo = 'bar'
const foo: 'bar' = 'bar'

foo = 'foorbar'		// not allowed

不过上面的第二种写法没有太大意义,但是利用union type,可以限制某一变量的取值范围

const foo: 'foo' | 'bar' = 'bar'
foo = 'foo'			// ok
foo = 'foobar'	// not ok

union type 不仅仅可以组合相同类型的 type,下面的写法也是可以的

type Foo = 'bar' | number

let foo: Foo = 1		// ok
foo = 'bar'					// ok
foo = 'foobar'			// not ok

null & undefined

TypeScript 和 JavaScript 一样,也有 null 和 undefined。但是它们的行为取决于 strictNullChecks flag 是否开启

strictNullChecks off

null 和 undefined 仍然可以被正常访问,也能当做属性赋值给任意值。这和 C# Java 类似,并不做 null checks。

strictNullChecks on

null undefined 是大多数 bug 的来源,因此推荐打开 strictNullChecks

当 strictNullChecks 打开时,需要在访问可能为空的值时,提前判空

! 断言

如果能 100% 保证变量不会为空,可以使用 ! 断言,以省去判空逻辑

function foo(x: number){
  console.log(x!.toFixed(2))
}

Enums 枚举类型

Enums 分为数字型和字符串型

数字型

// 如果不指定,默认从 0 开始
enum Direction {
  Up = 1, Down, Left, Right
}

字符串型

enum Direction {
  Up = "UP",
  Down = "DOWN",
  Left = "LEFT",
  Right = "RIGHT"
}

Enums 并不是 TypeScript 对 JavaScript 在**“类型系统层面”**上的扩展,因为 JavaScript 本身并没有枚举类型。如上面的数字型 enum 在 tsc 编译后的 js 文件是这样的:

var Direction;
(function (Direction) {
    Direction[Direction["Up"] = 1] = "Up";
    Direction[Direction["Down"] = 2] = "Down";
    Direction[Direction["Left"] = 3] = "Left";
    Direction[Direction["Right"] = 4] = "Right";
})(Direction || (Direction = {}));

Last updated 2 years ago