知道:TypeScript 类型注解
示例代码:
// 约定变量 age 的类型为 number 类型
let age: number = 18
age = 19
: number
就是类型注解,它为变量提供类型约束。错误演示:
let age: number = 18
// 报错:不能将类型“string”分配给类型“number”
age = '19'
小结:
知道:ts 有哪些类型,掌握:原始类型使用
TS 常用类型:
JS 已有类型
number
string
boolean
null
undefined
原始类型:
let age: number = 18
let myName: string = '黑马程序员'
let isLoading: boolean = false
let nullValue: null = null
let undefinedValue: undefined = undefined
掌握:数组类型的两种写法
let numbers: number[] = [1, 3, 5]
let strings: Array = ['a', 'b', 'c']
推荐使用:
number[]
写法思考:
掌握:通过联合类型将多个类型合并为一个类型
联合类型 Arrary<类型1 | 类型2 |类型3>
需求:数组中有 number
和 string
类型,这个数组的类型如何书写?
let arr: (number | string)[] = [1, 'a', 3, 'b']
定义:
|
连接,代表类型可以是它们当中的其中一种,这种类型叫:联合类型
练习:给一个定时器 ID 加类型
let timer: number | null = null
timer = setInterval(() => {}, 1000)
掌握:使用类型别名语法给类型取别字
示例代码:
// let arr: ( number | string )[] = [1, 'a', 4]
// 类型别名: type 类型别名 = 具体类型
type CustomArr = (number | string)[]
let arr: CustomArr = [1, 'a', 4]
类型别名:
type 类型别名 = 具体类型
基本语法使用场景:
简化
该类型的使用type CustomArr = (number | string)[]
let arr: CustomArr = [1, 'a', 4]
let arr2: CustomArr = [2, 'b', 8]
掌握:给函数指定类型
参数
和 返回值
指定类型。分别指定
参数和返回值类型同时指定
参数和返回值类型示例代码 1:分别指定
// 函数声明
function add(num1: number, num2: number): number {return num1 + num2
}// 箭头函数
const add = (num1: number, num2: number): number => {return num1 + num2
}
示例代码 2:同时指定
type AddFn = (num1: number, num2: number) => numberconst add: AddFn = (num1, num2) => {return num1 + num2
}
注意:
通过类似箭头函数形式的语法来为函数添加类型,只适用于 函数表达式
掌握:void 函数返回值类型
void
const say = (): void => {console.log('hi')
};
void
const say = () => {console.log('hi')
}
注意:
JS
中如果没有返回值,默认返回的是 undefined
void
和 undefined
在 TypeScript
中并不是一回事undefined
那返回值必须是 undefined
const add = (): undefined => {return undefined
}
掌握: 使用
?
将参数标记为可选
可选参数
语法,参数后加 ?
即可const fn = (n?: number) => {// ..
};
fn()
fn(10)
slice
函数,定义函数参数类型const mySlice = (start?: number, end?: number) => {console.log('起始Index:', start, '结束Index:', end);
}
mySlice()
mySlice(1)
mySlice(1, 2)
注意:
(start?: number, end: number)
这样是不行的掌握:对象类型语法
属性
方法
的类型,因为对象是由属性和方法组成的。Person定义的对象值,调用时,必须得对用,否则报错,接口就没有这个要求
let person: {name: stringsayHi: () => void
} = {name: 'jack',sayHi() {}
};
// 例如:axios({url,method}) 如果是 get 请求 method 可以省略
const axios = (config: { url: string; method?: string }) => {}
// {} 会降低代码可阅读性,建议对象使用类型别名
// const axios = (config: { url: string; method?: string }) => {}
type Config = {url: stringmethod?: string
}
const axios = (config: Config) => {}
小结:
{sayHi:()=>void}
{name?: string}
{}
如何提供可阅读性?类型别名
掌握:使用 interface 声明对象类型
小结:
interface
后面是接口名称,和类型别名的意思一样。接口名称
作为变量的类型使用。一个
属性或方法,每一行不需要加分号。掌握:使用 extends 实现接口继承,达到类型复用
思考:
interface Point2D {x: numbery: number
}
interface Point3D {x: numbery: numberz: number
}
继承:
extends
实现继承复用interface Point2D {x: numbery: number
}
// 继承 Point2D
interface Point3D extends Point2D {z: number
}
// 继承后 Point3D 的结构:{ x: number; y: number; z: number }
小结:
interface 接口A extends 接口B {}
接口A
拥有 接口B
的所有属性和函数的类型声明掌握:使用
交叉类型
实现接口的继承效果
Point2D
与 {z: number}
类型合并得到 Ponit3D
类型// 使用 type 来定义 Point2D 和 Point3D
type Point2D = {x: numbery: number
}// 使用 交叉类型 来实现接口继承的功能:
// 使用 交叉类型 后,Point3D === { x: number; y: number; z: number }
type Point3D = Point2D & {z: number
}let o: Point3D = {x: 1,y: 2,z: 3
}
小结:
&
可以合并连接的对象类型,也叫:交叉类型
了解:interface 和 type 的相同点和区别
自由选择
。可扩展
的。interface | type |
---|---|
支持:对象类型 | 支持:对象类型,其他类型 |
复用:可以继承 | 复用:交叉类型 |
不同的点:
type Person = {name: string
}
// 标识符“Person”重复 Error
type Person = {age: number
}
interface Person {name: string
}
interface Person {age: number
}
// 类型会合并,注意:属性类型和方法类型不能重复定义
const p: Person = {name: 'jack',age: 18
}
小结:
extends
, type 使用 &
知道:TS 的的类型推断机制作用
发生类型推断的几个场景场景:
// 变量 age 的类型被自动推断为:number
let age = 18
// 函数返回值的类型被自动推断为:number
const add = (num1: number, num2: number) => {return num1 + nu m2
}
建议:
充分利用TS推断
的能力,提高开发效率。Vscode
提示看到类型知道:什么是字面量类型
18
'jack'
['a']
{age: 10}
等等。js字面量
作为变量类型,这种类型就是字面量类型。// : 'jack' 是字面量类型
let name: 'jack' = 'jack'
// : 18 是字面量类型
let age: 18 = 18// 报错:不能将类型“19”分配给类型“18”
age = 19
思考:这两个变量的类型是什么?
let str1 = 'Hello TS'
const str2 = 'Hello TS'
string
, str2 类型是 Hello TS
str2
是 const
声明的,值只能是 Hello TS
,所以类型只能是 Hello TS
知道:字面量类型的应用场景
例如:性别只能是 男 和 女,不会出现其他值。
// let gender = '男'
// gender = '女'
// ------------------------
type Gender = '男' | '女'
let gender: Gender = '男'
gender = '女'
小结:
例子:
// 使用自定义类型:
type Direction = 'up' | 'down' | 'left' | 'right'function changeDirection(direction: Direction) {console.log(direction)
}// 调用函数时,会有类型提示:
changeDirection('up')
direction
的值只能是 up/down/left/right
中的任意一个string
类型,使用字面量类型更加精确、严谨应用场景:
当我们需要使用类型,但是不知道的时候,用它来替代,但是如果后期知道了,就改回明确类型
小结:
any
的使用越多,程序可能出现的漏洞越多,因此不推荐使用 any
类型,尽量避免使用。枚举的默认本质就是数值,它是给程序员看的,是为了更好的阅读
方便程序员看懂啥意思
// 枚举的属性,首字母大写,值如果不写默认从0开始自增
// 如果我们有给枚举指定数值,那么它后续的值会自增
enum Direction {Up = 10,Down,Left,Right = 18
}//Down=>11 Left=>12
// 如果是字符串枚举,如果你指定了值,必须全部指定,因为它不像数值那样可以递增
enum Direction {Up = 'Up',Down = 'Down',Left = 'Left',Right = 'Right'
}
有时候你会比 TS 更加明确一个值的类型,此时,可以使用类型断言来指定更具体的类型。 比如
// aLink 的类型 HTMLElement,该类型只包含所有标签公共的属性或方法
// 这个类型太宽泛,没包含 a 元素特有的属性或方法,如 href
const aLink = document.getElementById('link')
A
元素,可以通过 类型断言
给它指定一个更具体的类型。const aLink = document.getElementById('link') as HTMLAnchorElement
as
关键字实现类型断言as
后面的类型是一个更加具体的类型(HTMLAnchorElement 是 HTMLElement 的子类型)例如:
const img = document.getElementById('img') as HTMLImageElement
// 如果不知道标签的类型:document.querySelector('div') 鼠标摸上去就可以看见
TIP
掌握:泛型函数基本使用,保证函数内类型复用,且保证类型安全
// 函数的参数是什么类型,返回值就是什么类型
function getId(id: T): T {return id
}let id1 = getId(1)
let id2 = getId('2')
// TS会进行类型推断,参数的类型作为泛型的类型 getId('2')
小结
, T
是类型参数,是个类型变量,命名建议遵循大驼峰即可。T
什么时候确定? // 我需要的类型 { name: string, age?: number } 但是推断出来是 { name: string}
let id2 = getId({name:'jack'})
掌握:泛型别名基本使用,实现类型复用
// 对后台返回的数据进行类型定义
type User = {name: stringage: number
}type Goods = {id: numbergoodsName: string
}type Data = {msg: stringcode: numberdata: T
}// 使用类型
type UserData = Data
type GoodsData = Data
小结:
<类型参数>
就是泛型语法, 使用的时候传入具体的类型即可
是一个变量,可以随意命名,建议遵循大驼峰即可。复用性
和灵活性
掌握:泛型接口基本使用,实现类型复用,了解内置泛型接口
// 对象,获取单个ID函数,获取所有ID函数,ID的类型肯定是一致的,但是可能是数字可能是字符串
interface IdFn {id: () => Tids: () => T[]
}const idObj: IdFn = {id() { return 1 },ids() { return [1, 2] }
}const idObj2: IdFn = {id() { return 'a' },ids() { return ['a', 'b'] }
}
<类型变量>
,那么,这个接口就变成了泛型接口,接口中所有成员都可以使用类型变量。内置的泛型接口:
const arr = [1, 2, 3]
// TS有自动类型推断,其实可以看做:const arr: Array = [1, 2, 3]
arr.push(4)
arr.forEach((item) => console.log(item))