常见的三种值类型
number(数字类型)
// 申明一个数字类型的值
let a: number
a = 10
//不仅可以给形参设置类型,还可以给返回值设定类型
let sum (numA: number, numB: number) :number{
return numA + numB
}
string(字符串类型)
// 申明一个字符串类型的值
let b: string = 'hello'
boolean(布尔类型)
// 申明一个bool类型的值
let c: boolean = true
let typeBoolean: boolean
//虽然有该类型,但是TS也非常智能,在赋值时如未指定类型,则会自动识别类型。鉴于boolean只有两个值,个人建议省略
let typeFlag1 = true
let typeFlag2 = false //均自动识别变量为boolean类型
PS:类型注释
冒号 + 类型的叫类型注释
即: string这种叫类型注释
其他常见类型
字面量类型
// 字面量进行类型申明(字面量:即就是这个值本身)
let aa: 10
// a修改为其他值就会报错
aa = 11
// 实际开发中很少这么用,但是我们可以这么用
// 申明一个变量等于男或者女
let sex: 'male' | 'female'
// 我们使用的时候就可以赋值其中一个值,赋值其他值就会报错
sex = 'male'
sex = 'female'
sex = 'hello'
联合类型
// | 线可以用来连接多个类型(联合类型)
// 联合类型的符号是 |
// 除了用在字面量中,常规的使用当中有的更多
let bb: boolean | number
bb = true
bb = 123
// 赋值字符串,就错了
bb = 'hi'
any类型(任意类型)
// 申明任意类型的数据
// any表示任意类型,一个变量设置为any后相当于对该变量关闭了TS的类型检测
let cc: any
cc = 123
cc = true
cc = 'hi'
// 隐式any,即申明,但是不设置类型,如下
let dd
dd = 123
unknown类型
// unknown 表示未知类型
let ee: unknown
ee = 123
ee = true
ee = 'hi'
any和unknown比较
// 那么any和unknown有什么区别呢?
// any可以赋值给任何变量
let ff: string
ff = cc
// unknown实际上就是一个类型安全的any
// unknown类型的变量不能直接赋值给其他变量
let gg: string
gg = ee
// 如何处理这种报错呢?
// 1.类型判断
if(typeof ee === 'string') {
gg == ee
}
// 2.类型断言(意思是,ee就是一个string,你就放心用了)
gg = ee as string
gg = <string>ee
PS:类型断言
- 断言语法
-
- 1.变量 as 类型
- 2.<类型>变量
void类型
// void用来表示空,以函数为例,表示没有返回值的函数
function fn():void {
console.log(11111)
}
// never表示永远不会返回结果
function fn2(): never {
throw new Error('出错了')
}
object类型
// object表示一个js对象
let obj: object
obj = {}
obj = function() {
}
// js中对象太多了,一般不像上面这样申明,那么我们在上面时候用这种形式呢?
// 比如我们申明一个变量,但是我们希望变量中包含某个值时
let obj2: {name: string}
// 这样是正确的
obj2 = {name: '景天'}
// 这样就会报错
obj2 = {}
// 写多了也会报错
obj2 = {name: '景天',age:18}
// 那么我们就是要age,而且age也不确定有没有,怎么写呢?
let obj3: {name: string,age?: number}
// 这样都正确
obj3 = {name: '景天'}
obj3 = {name: '景天',age:18}
// 但是实际开发中,我们还会有不确定有多少其他属性值,怎么处理呢?
let obj4: {name: string, [propName:string]:any}
// 这样的话,除了要求的值,其他随便写不写,写什么都无所谓了
obj4 = {
name: '景天',
age: 18,
c: true
}
函数
// 如何设置函数的类型申明呢?
// 这表示函数两个参数,都是number类型,返回值也是number类型
let fn1: (a:number,b:number) => number
fn1 = function(n1,n2) {
return n1 + n2
}
// 函数中使用另一种类型限制
// ): number是限制返回值的类型的
function add(a: number,b:number): string {
return String(a + b)
}
数组
/*
array,两种申明方式(这也是一种泛型的写法)
1. 类型[]
2. Array<类型>
*/
// 纯字符串数组
let arr: string[]
arr = ['a','b','c']
// 纯数字数组
let arr2: Array<number>
arr2 = [1,2,3]
元组
// tuple(元组):固定长度的数组
let yuanzu: [string,number]
yuanzu = ['111',222]
枚举
// enum: 枚举
// 申明一个枚举类
enum Gender {
male = 1,
female = 0
}
let hh: {name: string,gender: Gender}
hh = {
name: '景天',
gender: Gender.male
}
类型的别名
// 类型的别名
type myType = string
// 这相当于还是string
let ii: myType
// 但是这样的话,通常没什么意义,而我们用字面量类型的时候,有时候可以使用
type jjType = 1 | 2 | 3 | 4 | 5 | 6
// 这样无论我们多少个地方使用,都可以直接用了
let jj: jjType
let kk: jjType
let ll: jjType
// 任何类型都可以有别名
// 比如object
type obj = {
x:number,
y:number
}
// 别名的扩展
// 一个新的obj1在上面的obj的基础上扩展
type obj1 = obj & {
z: number
}
TS泛型
TS泛型是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的特性
泛型用法
在函数中使用泛型
function test <T> (arg:T):T{
console.log(arg);
return arg;
}
test<number>(111);// 返回值是number类型的 111
test<string | boolean>('hahaha')//返回值是string类型的 hahaha
test<string | boolean>(true);//返回值是布尔类型的 true
使用方式类似于函数传参,传什么数据类型,T就表示什么数据类型, 使用表示,T也可以换成任意字符串。
在接口中使用泛型
// 注意,这里写法是定义的方法哦
interface Search {
<T,Y>(name:T,age:Y):T
}
let fn:Search = function <T, Y>(name: T, id:Y):T {
console.log(name, id)
return name;
}
fn('li',11);//编译器会自动识别传入的参数,将传入的参数的类型认为是泛型指定的类型
在类中使用泛型
class Animal<T> {
name:T;
constructor(name: T){
this.name = name;
}
action<T>(say:T) {
console.log(say)
}
}
let cat = new Animal('cat');
cat.action('mimi')
泛型约束
使用接口约束泛型
interface Person {
name:string;
age:number;
}
function student<T extends Person>(arg:T):T {
return arg;
}
student({name:'lili'});//类型 "{ name: string; }" 中缺少属性 "age",但类型 "Person" 中需要该属性
student({ name: "lili" , age:'11'});//不能将类型“string”分配给类型“number”
student({ name: "lili" , age:11});
数组泛型
let arr:Array =[1,2,3] === let arr:number[]=[1,2,3]
泛型工具类型
Partial
partial的作用就是将某个类型中的属性全部变为可选项?
interface Person {
name:string;
age:number;
}
function student<T extends Person>(arg: Partial<T>):Partial<T> {
return arg;
}
Record
Record<K extends keyof any, T>的作用是将K中所有的属性转换为T类型;示例:
interface PageInfo {
title: string
}
type Page = 'home'|'about'|'other';
const x: Record<Page, PageInfo> = {
home: { title: "xxx" },
about: { title: "aaa" },
other: { title: "ccc" },
};
Pick
Pick<T, K extends keyof T>的作用是将某个类型中的子属性挑出来,变成包含这个类型部分属性的子类型,示例:
interface Todo {
title:string,
desc:string,
time:string
}
type TodoPreview = Pick<Todo, 'title'|'time'>;
const todo: TodoPreview ={
title:'吃饭',
time:'明天'
}
Exclude
Exclude<T,U>的作用是将某个类型中属于另一个类型的属性移除掉,示例:
type T0 = Exclude<"a" | "b" | "c", "a">; // "b" | "c"
const t:T0 ='b';
ReturnType
returnType的作用是用于获取函数T的返回类型,示例:
type T0 = ReturnType<() => string>; // string
type T1 = ReturnType<(s: string) => void>; // void
type T2 = ReturnType<<T>() => T>; // {}
type T3 = ReturnType<<T extends U, U extends number[]>() => T>; // number[]
type T4 = ReturnType<any>; // any
type T5 = ReturnType<never>; // any
type T6 = ReturnType<string>; // Error
type T7 = ReturnType<Function>; // Error
TypeScript高级类型
Partial
Partial 类型的定义
/**
* Make all properties in T optional
*/
type Partial<T> = {
[P in keyof T]?: T[P];
};
假设我们有一个定义 user 的接口,如下
interface IUser {
name: string
age: number
department: string
}
经过 Partial 类型转化后得到
type optional = Partial<IUser>
// optional的结果如下
type optional = {
name?: string | undefined;
age?: number | undefined;
department?: string | undefined;
}
Partial 可以快速把某个接口类型中定义的属性变成可选的(Optional):例子
interface People {
age: number;
name: string;
}
const Jerry:People = {
age: 10,
name: 'Jerry'
};
type AnonymousPeople = Partial<People>;
const tom:AnonymousPeople = {
name: 'Tom'
};
Required
生成一个新类型,该类型与 T 拥有相同的属性,但是所有属性皆为必选项
// 源码
type Require<T> = {
[p in keyof T]-?: T[P]
}
// 例子:
interface Foo {
name: string
age?: number
}
type Bar = Required<Foo>
// 相当于
type Bar = {
name: string
age: string
}
Readonly
生成一个新类型,T 中的 K 属性是只读的,K 属性是不可修改的
// 源码:
type Readonly<T> = {
[p in keyof T]-?: T[P]
}
// 例子:
interface Foo {
name: string
age: number
}
type Bar = Readonly<Foo>
// 相当于
type Bar = {
readonly name: string
readonly age: string
}
Pick
生成一个新类型,该类型拥有 T 中的 K 属性集 ; 新类型 相当于 T 与 K 的交集
// 源码:
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
// 例子:
interface Foo {
name: string;
age?: number;
gender: string;
}
type Bar = Pick<Foo, 'age' | 'gender'>
// 相当于
type Bar = {
age?: number
gender: string
}
const todo: Bar= {
age?: 3,
gender: 男
};
console.log(todo)
Omit
生成一个新类型,该类型拥有 T 中除了 K 属性以外的所有属性
// 源码:
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>
// 例子:
type Foo = {
name: string
age: number
}
type Bar = Omit<Foo, 'age'>
// 相当于
type Bar = {
name: string
}
Exclude
如果 T 是 U 的子类型则返回 never 不是则返回 T
// 源码:
type Exclude<T, U> = T extends U ? never : T
// 例子:
type A = number | string | boolean
type B = number | boolean
type Foo = Exclude<A, B>
// 相当于
type Foo = string
Extract
和 Exclude 相反
// 源码:
type Extract<T, U> = T extends U ? T : never
// 例子:
type A = number | string | boolean
type B = number | boolean
type Foo = Extract<A, B>
// 相当于
type Foo = number | boolean