Skip to content

基础类型

数组

1.下面是声明数组的 类型 为字符串

typescript
let hd:string[] =[]
hd.push('houdunren','后盾人')

2.通过范型声明数组

typescript
const arr = Array<string>("hello world")

元组

明确每个数组成员类型(或者值类型)的数组为元组

typescript
let hd: [string, number, boolean]
hd = ['houdunren.com', 2090, true]

对象

1.下面是声明对象类型但不限制值类型

typescript
let hd:object

2.限定对象值类型

typescript
let hd:{name: string,year:number}

hd={name:'后盾人',year:2010}

3.属性后面跟上? 用来指定 url 为可选值,这样的属性是非必填项

typescript
//属性后面加 ? 号声明属性为可选的
let hd:{ name: string,year:number,url?:string }
hd = { name:'后盾人',year:2010 }

索引签名

1.如果有明确的索引名称可以使用下面方式来定义签名

typescript
type HOUDUNREN = {
  name: string
  city: string
}

let hd: HOUDUNREN = {
  name: 'houdunren',
  city: 'beijing'
}

2.如果定义任意属性的签名,可以使用索引签名完成

typescript
type HOUDUNREN = {
  [key: string]: keyof any
}

let hd: HOUDUNREN = {
  name: 'houdunren'
}

any

使用 any 指包含所有值的顶部类型,所以 any 不进行类型检查,等于关闭了 TS 对该变量的严格类型校验

  • 使用 any 类型等同于使用纯 JavaScript 的开发方式
  • any 类型是顶部类型,所有其他类型是他的子类型
  • 使用 any 类型将失去 typescript 静态类型的强制检测
  • 只有在描述一个根本不知道的类型时使用 any

1.下面是设置基本 any 的示例

typescript
//等同于说明hd变量可以是任意类型
let hd:any

//以下赋值不会报错
hd='houdunren'
hd=2010
hd=true
hd=[]
hd ={}
hd= class{}

2.在数组中使用 any 类型,可以设置任意类型的值

typescript
let hd:any[] =['houdunren.com','后盾人',2010,true]

//或者通过范型声明数组成员为any类型
let hdcms:Array<any> = ['houdunren.com','后盾人',2010,true]

unknown

unknown 类型也是顶部类型这与 any 一样

  • unknown 用于表示未知的类型
  • 会进行 TS 的类型检查,any 不进行 TS 检查
  • 使用 unknown 类型时可以使用 as 类型断言来明确类型

1.下面是 any 与 unknown 赋值上的区别,unknown 需要明确类型后赋值,any 则不需要

typescript
let xj:any ='后盾人'
let hd:unknown = 'houdurnen'

let a:string = xj
let b:string=hd //报错: 'unknown'未知类型不能赋值给'string'类型

// unknown 类型需要明确类型后赋值
let c:string=hd as string

2.可以把任何值赋值给 unknown 类型,但在使用时需要指明类型

typescript
let hd: unknown
hd = 'houdunren'
hd = 100

//在使用时,TS不知道是什么类型,所以需要使用类型断言进行告之
let c = hd as number + 20

3.使用 keyof 类型工具时 unknown 与 any 的区别

typescript
type HD<T> = { [P in keyof T]: string }

//{[x: string]: string;}
type HOUDUNREN = HD<any>

//结果为{},因为 keyof unknow 是never,所以被忽略了
type XJ = HD<unknown>

4.any 与 unknown 在类型检查上是有区别的

typescript
let houdunren: any
houdunren.show();//any不进行类型检查,所以不会报错

let hd: unknown

hd.show();//unknown进行类型检查,unknown是未知类型所以报错

5.使用 unknown 类型时,结合 typeof 进行类型判断,根据不同类型使用不同逻辑

typescript
function get(val: unknown) {
  if (typeof val === 'number') {
    return val * 100;
  }
  return 0
}

console.log(get(100));  //NaN

null & undefined

1.null 与 undefined 也是变量类型,用于定义值为 null 或 undefined

typescript
let hd:null =null

let houdunren:undefined=undefined

2.strictNullChecks,当配置项启用 strictNullChecks 时,null 与 undefined 只能赋值给 void、null、undefined 类型

typescript
let hd:string = undefined; //配置strictNullChecks=true 时将报错

void 类型的值为 null 或 undefined,常用于对函数返回值类型定义

  • 严格模式(tsconfig.json 配置中关闭strict)时,void 值只能是 undefined(有关 TS 配置会在后面章节介绍)
  • 如果函数没有返回值请使用 void 类型,这会使用代码更易读,并可对不小心造成的函数返回内容进行校验
  • 你也可以将 void 理解为对返回 null 或 undefined 的函数返回值声明
  • TypeScript 中,不返回任何内容的 void 函数实际上返回的是 undefined

1.void 类型的值可以是 null 或 undefined,但如果 TS 配置开启了 strictstrictNullChecks则不允许 void 为 null

typescript
let hd:void = undefined;
let houdunren:void = null;

2.TypeScript 中,不返回任何内容的 void 函数实际上返回的是 undefined

3.经过 void 限定后是不允许函数返回内容的,所以以下代码将报错

typescript
function hd():void{
    return 'hd'
}

never

never 是任何类型的子类型,可以赋值给任何类型,没有类型是 never 的子类型。

never 类型的特点

  • never 没有任何子类型,所以任何类型都不可以赋值给 never
  • 函数抛出异常或无限循环时返回值是 never
  • 可以将每个类型理解为某类值的集合,比如 number 类型包含所有数字,但 never 类型没有任何值。
typescript
//函数抛出错误时返回值类型是never
function hd():never{
	throw new Error("出错了")
}

1.never 是所有类型的子类型,可以分配给任何类型,所以下面类型为 string

typescript
type HOUDUNREN = never extends string ? string : boolean //string

2.其他类型不可以分配给 never 类型

typescript
type HOUDUNREN = string extends never ? string : boolean //boolean

3.never 是所有类型的子类型,所以下面实际类型是 string | number

typescript
type HOUDUNREN = never | string | number //string | number

union 联合类型

union 联合类型是多个类型的组合,使用 | 进行连接,| 类似于 javascript 中的 || 或运算符。

1.下面是为变量声明字符串或数值类型

typescript
let hd:string | number = 'houdunren.com'
hd = 2010

2.下面是为数组声明多种类型

typescript
let hd:(string | number | boolean)[]  = []
hd.push('houdunren.com',2010,true)

3.也可以使用泛型方式声明(泛型的详细使用后面内容会介绍)

typescript
//数组接受范型参数并传递联合类型,约束数组成员是联合类型
let hd:Array<string|number|boolean>  = []
hd.push('houdunren.com',2010,true)

交叉类型

交差类型是将 interface、object 等进行合并,组合出新的类型

  • interface、object 进行属性合并
  • 交叉时要保证类型是一致的,string 与 number 交叉将得到 never 类型

1.对象类型会进行属性合并

typescript
interface A { name: string }

type B = { age: number }

let c: A & B = { name: '后盾人', age: 100 }

2.两个类型有相同属性,且类型不同时,返回类型为 never

typescript
let a = { name: '后盾人' }
let b = { age: 10, name: true }

//这里类型交叉之后获得的新类型应该是{name:never,age:number}
type HD = typeof a & typeof b


//报错 不能将类型“string”分配给类型“never”。
let c: HD = { age: 30, name: 'houdunren' }

//解决方案,将a 或者 b 的name索引移除
let a = { name: '后盾人' }
let b = { age: 10, name: true }

//通过Pick移除name索引
type HD = typeof a & Pick<typeof b, 'age'>

let c: HD = { age: 30, name: 'houdunren' }

3.通过交叉类型将 User 类型组合成新的 Member 类型

typescript
type User = { name: string, age: number }
type Member = { avatar: string } & User

let member: Member = {
  name: 'houdunren', avatar: 'xj.png', age: 30
}

4.stringnumber 因为类型不同,交叉计算后得到 never 类型

typescript
type HD = string & number;

type HD2 = 'a' & 'b'

函数

下面我们来掌握函数在 TypeScript 中的使用方式。

参数类型
typescript
function sum(a, b) {
    return a + b;
}

console.log(sum('a', 3));//a3

因为这是个计算函数,下面来设置参数类型,让代码更健壮。

因为限定了数值类型,所以函数参数必须传递数值

typescript
function sum(a: number, b: number) {
    return a + b;
}

console.log(sum(2, 3));

如果参数是可选的,使用 ? 修饰,如果参数设置默认值了就不需要可选参数符号?

返回值类型

系统自动推断

typescript
function sum(a: number, b: number) {
    return a + b;
}
//函数结构为 function sum(a: number, b: number): number

我们也可以明确返回类型

typescript
function sum(a: number, b: number): string {
    return `计算结果是:${a + b}`;
}

console.log(sum(3, 3));

下面是箭头函数的表示方法

  • 因为函数体只有一条语句,所以省略了{}

    typescript
    let sum = (a: number, b: number): string => `计算结果是:${a + b}`
  • 当函数没有明确返回值时,使用 void 类型。TS 会自动推断,建议明确声明 void 类型

    typescript
    let hd = (): void => {
        console.log('后盾人');
    }
    hd()
参数声明

有时多个函数会用到相同的类型的参数,比如下面的示例

typescript
let addUser = (user: { name: string; age: number }): void => {
  console.log('添加用户')
}

let updateUser = (user: { name: string; age: number }): void => {
  console.log('更新用户')
}

updateUser({ name: '后盾人', age: 18 })

我们可以使用 type 对参数对象进行声明,通过这种复用的手段可以很好的优化代码

typescript
type userType = { name: string; age: number }

let addUser = (user: userType): void => {
  console.log('添加用户')
}

let updateUser = (user: userType): void => {
  console.log('更新用户')
}

updateUser({ name: '后盾人', age: 18 })
函数定义

对没有返回值函数的定义

typescript
let hd: () => void

hd = (): void => console.log('后盾人')

下例是对 hd 函数的定义:

  • 函数定义中声明的变量 a,在具体实现函数是可以为任何名称

    typescript
    let hd: (a: number, b: number) => number
    
    hd = (x: number, y: number): number => {
        return x + y
    }

    也可以在声明函数时就定义函数的结构

    typescript
    let hd: (a: number, b: number) => number = (x: number, y: number): number => {
        return x + y;
    }
    
    console.log(hd(2, 3));
  • 下例中的参数 u 不定义类型结构,TS 也是可以推断出来的

    typescript
    let addUser: (user: { name: string, age: number }) => boolean;
    
    addUser = (u: { name: string, age: number }): boolean => {
        console.log('添加用户');
    
        return true;
    }
剩余参数

下面的求和函数接收多个参数

typescript
function sum(...args: any[]): number {
    return args.reduce((s, n) => s + n, 0);
}

console.log(sum(1, 2, 3, 4, 5));
Tuple 元组

元组与数组类似,但元组要为每个值进行类型声明

数组只是定义了值的类型,并没有约束某个位置的值必须是什么类型,请看下例

typescript
const arr: (number | string | boolean)[] = ['后盾人', 2030, true];

arr[1] = 'houdunren.com' //不会报错,可以将原来是数值的更改为字符串,这是数组允许的类型范围
arr[10] = '向军老师' 			//不会报错,类型也是允许的
console.log(arr);

下面看使用元组来限制值的类型

typescript
const hd: [string, number] = ['后盾人', 2030]
hd[0] = true //报错,第一个值必须是字符串
函数重载

函数的参数类型或数量不同时,会有不同的返回值,函数重载就是定义这种不同情况的函数。

重载签名

重载签名是对函数多种调用方式的定义,定义不同的函数参数签名与返回值签名,但是没有函数体的实现。

  • 使用函数时调用的是重载签名函数,在 vscode 代码跟踪时也会定位到重载签名
  • 将从第一个重载签名尝试调用,向下查找是否有匹配的重载签名
  • 定义重载签名可以在 idea、vscode 中拥有更好的代码提示
typescript
function getId(id: string): string;
function getId(id: number): number;

实现签名

实现签名是是函数功能的实现,对参数与返回值要包扩符合函数签名的宽泛类型。

  • 重载签名可以是多个,实现签名只能是一个
  • 实现签名是最终执行的函数
  • 用户在调用时调用的是重载签名
  • 重载签名可被调用,实现签名不能被调用
  • 实现签名要使用通用类型
//重载签名
function getId(id: string): string;
function getId(id: number): number;

//实现签名
function getId(id: unknown): unknown {
	if (typeof id === 'string') {
		return id;
	}
	return id;
}

//function getId(id: string): string (+1 overload)
getId('后盾人');

实现签名要使用通用的类型

typescript
function getId(id: string): string;
function getId(id: number): number;

//报错:因为实现签名不通用 「不能将类型“unknown”分配给类型“string”」
function getId(id: unknown): string {
	if (typeof id === 'string') {
		return id;
	}
	return id;
}

getId('后盾人');