1、基础类型
字符串
string,字符串类型
let name: string = 'penn'
数值
number,数值类型
let age: number = 12
布尔值
boolean,布尔值类型
let isMan: boolean = true
数组
使用类型[]或者Array<类型>表示
// 字符串数组
// 声明方式1
let arrStr: string[] = ['x1', 'x2']
// 声明方式2
let arrStr: Array<string> = ['x1', 'x2']
// 数值数组
// 声明方式1
let arrNum: number[] = [1, 2]
// 声明方式2
let arrNum: Array<number> = [1, 2]
元组
定义已知数量和类型的数组。
let arr: [number, string] = [1, 'name']
枚举
默认从0开始取值。
enum Color { Blue, Green, Red }
// Color.Blue -> 0
// Color[0] -> Blue
enum Color { Blue = 2, Green = 3, Red = 4 }
// Color.Blue -> 2
// Color[2] -> Blue
// Color JS对象
// {2: 'Blue', 3: 'Green', 4: 'Red', Blue: 2, Green: 3, Red: 4}
any
任意类型,当不知道当前对象具体有什么类型时,可以使用any来规避类型的检验。
let arr: any = 'name'
void
返回值为空,一般使用在函数的返回值类型,当没有返回值时,可使用void
undefined是void的子类型,因为undefined可以赋值给void
function fn(params): void {
// ...
}
null 和 undefined
与JS的null和undefined对应,在非<font style="color:rgb(191, 65, 74);">--strictNullChecks</font>情况下,null和undefined是所有类型的子类型。
never
表示达不到终点,没有确定值。如报错,无限循环。都是没有最终值的。
可以用于代码完整性保护(即判断代码逻辑写完了没有)
// 报错 抛出异常
function fn(): never {
throw new Error('error')
}
// 无限循环
function fn(): never {
wile(1) {
// ...
}
}
// 代码完整性保护
function validateCheck(val: never) {}
function someTypeCheck(val: number | string | boolean) {
if (typeof val === 'number') {
return 1
}
if (typeof val === 'string') {
return 2
}
if (typeof val === 'boolean') {
return 3
}
// 如果val值类型没有全部判断,则会类型报错
validateCheck(val)
}
object
对象类型,非原始类型的值都可以赋值。
let o: object = Object.create({})
设置某些固定属性名,其他随意,任意属性可以设置[propName: string]: any,propName只是一个变量,可以是任意值,如[a1: string]: any
let obj: { name: string, [propName: string]: any }
obj = { name: 'xx1', age: 1, work: () => {} }
类型断言
当需要一个类型值切换成自己想要的类型时,可是类型断言。
<>,as都可表示类型断言。
let data: any = '123'
// 确定data为字符串
console.log(<string>data.length)
console.log((data as string).length)
2、基本类型总结
unkown和any的区别
相同点
都是可以赋值任何值,不会报错
不同点
any变量可以赋值给任意类型的变量
unkown不能赋值给任意类型的变量
3、接口
接口一般用来定义对象,函数,类。
使用Interface来定义对象的具体类型。
接口可重复定义,将属性进行合并,重复属性类型必须一样,否则会报错。
子类可以赋值给父类。
interface IParams {
name: string
age: number
readonly height: number // 只读
work?: string // 可选属性
[propName: string]: any // 任意属性
}
let pramas: IParams = {
name: 'penn',
age: 100,
height: 100,
sex: 'man'
}
4、类型(type)
使用类型定义对象类型
type TParams = {
name: string
age: numebr
readonly height: number // 只读
work?: string // 可选属性
[propName: string]: any // 任意属性
}
let pramas: TParams = {
name: 'penn',
age: 100,
height: 100,
sex: 'man'
}
类型与接口的区别
- 类型不可重复定义,接口可以重复定义,并且会将类型相互合并。
5、类型断言
as
将变量声明成某种类型
是将大范围类型,断言成子类型
一般在变量有多种类型时,使用某种类型的方法时,需要直接声明该变量的具体类型才能使用这个方法
!
指定该变量一定不为空,一定是有值的。
function someTypeCheck(val: number | string | boolean | null) {
// 使用 as 断言
(val as string).charAt(1)
// 使用<>
(<string>val).charAt(1)
// 使用! 指定该变量一定有值
val!.toString()
}
6、函数类型声明
- 函数式声明
- 表达式声明
在函数中尽量少用this,使用this会导致类型推导不出来
如果需要定义this的类型,需要放在参数的第一位
function getObjKey1(this: { a: string, b: string }, key: 'a' | 'b') {
return this[key]
}
// 表达式声明
const getObjKey1 = function (this: { a: string, b: string }, key: 'a' | 'b') {
return this[key]
}
const obj = {
name: 'penn',
age: 18,
hasWork: true
}
// typeof 提取对象的类型
type TObj = typeof obj
// keyof 提取对象的属性值
type TKey = keyof TObj
function getObjKey2(this: TObj, key: TKey) {
return this[key]
}
函数声明重载
只能从子类型开始定义,且不能有具体实现,只是类型声明
function getData(val: number): number
function getData(val: string): string
function getData(val: number | string): number | string {
return val
}
7、泛型
类型变量,当当前的对象类型不能确定,只有在创建或执行的时候才知道具体类型,这个时候就可以使用泛型。
一般都是使用大写字母表示,常用T
// 现在需要实现一个方法,输入一个构造函数,需要返回该构造函数的实例
class Women {
constructor(public name: string) {}
}
class Man {
constructor(public name: string) {}
}
// 可用接口定义构造函数
interface IConstructor<T> {
new (...args: any[]): T
}
// function getInstance<T extends new (...args: any[]) => any>(cls: T): InstanceType<T> {
// function getInstance<T>(cls: IConstructor<T>) {
function getInstance<T>(cls: new (name: string) => T, name: string) {
return new cls(name)
}
在接口中定义泛型,泛型在接口右边表示未执行前就已经确定类型。泛型在属性左边表示,执行时才确认类型。
// 泛型在接口的位置
interface IFun<T> {
<R>(a: T, b: R): T
}
泛型可以赋默认值<T = string>
interface IParams<T = string> {
name: string
data: T,
length: number
}
泛型约束,限制泛型的类型在一定的范围只能,不是任意的。不限制默认就是任意类型。
使用extends限制泛型。
extends表示扩展,子类可以在父类的基础上进行扩展,但是一定要有父类的属性方法。
type TVal = string | number
interface IParams<T extends TVal> {
name: string
data: T,
length: number
}
// 报错:类型“boolean”不满足约束“TVal”
const obj: IParams<boolean> = {
name: '123',
data: true,
length: 2
}
// 写一个方法,获取对象的属性值
// 这样声明类型,只能限制一个对象,其他对象可能不适用
type TTarget = typeof obj1
type TKey = keyof TTarget
const getValue = (target: TTarget, key: TKey) => {
return target[key]
}
// 通用写法
const getValue = <T extends object, K extends keyof T>(target: T , key: K) => {
return target[key]
}
const obj1 = {
name: 'px1',
age: 18,
hobby: ['football', 'basketball']
}
getValue(obj1, 'hobby')