数据类型
number
const num: number = 12
string
const text: string = 'hello'
但是有些情况下,类型不一定是 string
,也可以是指定的某些值
let admin: '张三' | '小明'
admin = '张三'
console.log(admin)
boolean
const bol: boolean = true
object
const obj: object = {}
那么使用下面方式可以限定对象中每个属性的类型
let obj: { name: string; age: number }
obj = { name: 'admin', age: 12 }
如果有些参数是可选的,那么可以使用 ?
来标识
let obj: { name: string; age: number; url?: string }
obj = { name: 'admin', age: 12 }
array
数字或字符串的数组
const numArr: number[] = [1, 2, 3, 4]
const strArr: string[] = ['1', '2', '3']
多类型数组
const arr: (string | number | object)[] = ['12121', 121, {}]
数组还有另一种编写的格式
const arr: Array<string | number> = ['1', '2']
any
可以用 any
标记任何类型
let num: any
num = 1
num = true
num = '123'
unknown
unknown
为不知道是什么类型,但是其实是有类型的
let num: unknown // 一个变成设置 unknown 类型代表不确定
num = '这是一个文字' // 给变量赋值了字符串,现在知道类型了
let res: string = num as string // 给 res 赋值 num 并通过关键字 as 告诉赋值的是什么类型
console.log(res) // 这是一个文字
unknown
在有些时候还是很有意思的,比如在想将一个字符串赋值给一个数字的时候,这显然是不可以的,那么可以先使用 as
关键字赋值为 unknown
类型,再使用 as
转换为像要的类型
let num: string = '1213'
let res: number = num as unknown as number
console.log(res) // 1213
尽量少使用 any 类型
void
void
类型也就是 undefined
类型
let v1: void = undefined
比如一个函数,可能返回字符串,也有可能不返回值
function fun(): string | void {}
如果是 void
类型返回值的函数返回值也就是 undefined
never
never
和 void
不同,never
是什么结果都没有,比如下面函数就是什么结果都没有
function fun(): never {
throw new Error('err')
}
null
const n: null = null
undefined
const n: undefined = undefined
多类型
因为一个值可能会存在多种类型的时候,所以不能直接将某个值限定为一个类型
let text: number | string
text = '123'
text = 6666
Function
Function
类型的 F
必须要大写
函数参数也是可以限制类型的
如果某个参数的可选的,可以添加 ?
标识符
function fun(a: number, b: number, c?: number) {
return a + b
}
也可以定于函数的返回值类型
const add = (a: number, b: number = 12): string => {
return `幸运数字是${a + b}`
}
const res: string = add(10)
console.log(res)
如果函数没有返回值,简直将返回值定义为 void
类型,方便一眼就可以看出来
function fun(): void {
console.log('hello')
}
type
type
关键字可以将反复使用的类型以相当于定义变量的形式反复使用
比如下面两个函数都接受一个对象,是两个类型相同的对象,就可以使用 type
定义的类型进行约束
type userType = { name: String; age: number }
function add(user: userType): void {}
function change(user: userType): void {}
type 可以合并多个
type Name = {
name: string
}
type Age = {
age: number
}
type User = Name & Age
const user = {
name: '张三',
age: 12
}
或者可以指定一个类型满足即可
type Name = {
name: string
}
type Age = {
age: number
}
type User = Name | Age
const user = {
name: '张三'
}
元组
元组用于定义一个已知数量和数据类型的数组
const arr: [number, string, number] = [1, '123', 3]
enum 枚举
可以使用 enum
去定义枚举类型,这样可以把类型限制在指定的场景之内
enum isType {
type1 = '男',
type2 = '女'
}
const res: isType = isType.type1
console.log(res)
as 断言
普通断言,规定类型
let res = 123 as number
res = 999
console.log(res)
const
断言
比如使用 let
的时候声明一个变量,只要是字符串就可以随便修改
let a = '哈哈哈'
a = '你好'
console.log(a) // 你好
但是使用了 const
断言情况如下
let a = 'hello' as const
这样使用 const 断言之后,a
就不能随意赋值了,就只能赋值为 hello
也就相当于下面写法,a
只能是两个值其中的一个
const a: 'hello' | 'world' = 'hello'
断言数组
断言数组之后就会被转换为元组
const arr = ['123', 89, true] as const
定义的方式也可以像下面这样
const arr = <const>['123', 89, true]
as const 就是根据具体的值转换类型
如果明确某个变量是存在的,可以使用 !
来表示非空断言,下面两种写法相等
const el1: HTMLDivElement = document.querySelector('.app') as const
const el: HTMLDivElement = document.querySelector('.app')!
generics 泛型
泛型代表的是不确定的类型,宽泛的类型,比如下面例子中:
function msg(num) {
return num
}
console.log(msg('hello'))
console.log(msg(true))
上面代码中,无论函数传入什么类型,都会直接返回指定的类型,但是这些类型都是 any
,大多数时候我们并不希望是 any
所以这里就需要使用到了泛型。
所以就需要传递不同的参数的时候,动态的传递指定的类型。类型也是可以类型函数接收参数一样:
function msg<type>(num: type): type {
return num
}
console.log(msg<string>('hello'))
console.log(msg<boolean>(true))
类型的继承
使用 extends
可以继承一个属性
// 这里让 t 继承一个 { length: number }
function getLength<t extends { length: number }>(target: t): number {
// 类型 t 里面没用任何规范 可能不存在 length 属性
return target.length
}
console.log(getLength('setting'))
console.log(getLength([1, 2, 3, 4]))
或者也可以继承一个有长度的类型,比如 string
,或者联合类型
function getLength<t extends string>(target: t): number {
return target.length
}
function getLength2<t2 extends string | any[]>(target: t2): number {
return target.length
}
interface
- 在类中使用
定义一个类型的接口,比如下面类的定义,使用 implements
定义接口
interface AdminInterface {
name: string
age: number
}
class Admin implements AdminInterface {
name: string = '张三'
age: number = 12
}
如果类中没有定义接口中约束的数据的话,就会报错
- 在对象中使用
interface UserInterface {
name: string
age: number
sayName(): string
[key: string]: any
}
const user: UserInterface = {
name: 'admin',
age: 12,
sayName(): string {
return this.name
},
sex: '男'
}
- 接口继承
interface UserName {
name: string
}
interface UserAge extends UserName {
age: number
}
const user: UserAge = {
name: 'admin',
age: 12
}
- 多接口
interface UserName {
name: string
}
interface UserAge {
age: number
}
class Admin implements UserName, UserAge {
name: string = '张三'
age: number = 12
}
- 定义数组
下面使用枚举和接口同时限定
enum SexType {
GIRL,
BOY
}
interface User {
name: string
age: Number
sex: SexType
}
const user1: User = { name: '1', age: 12, sex: SexType.BOY }
const user2: User = { name: '211', age: 122, sex: SexType.GIRL }
const arr: User[] = [user1, user2]
- 定义函数
interface Pay {
(num: number): boolean
}
const pay: Pay = (num: number): boolean => true
- 接口声明合并
接口重复声明最终会合并
interface User {
num: number
}
interface User {
name: string
}
const pay: User = {
num: 123,
name: '张三'
}