一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情。
温馨提示: TS 是一个可选的静态的类型系统, 要是你用的不开心, 不用就行了 哈哈
如何进行类型约束
通过类型约束: 变量、函数的参数、函数的返回值, 这几种常用的值, 当有了类型约束才可以进行类型检查。
使用: 仅需要在 变量、函数的参数、函数的返回值位置上加上 :类型
基本类型
- number:数字
- string:字符串
- boolean:布尔
- null 和 undefined 是所有其它类型的子类型, 它们可以赋值给其它类型
举例:
let a:number = null; //success
let b:string = undefined; //success
这在 ts 中是合法的, 所以这里是存在隐患的, 为了避免这种情况可以在配置文件中加入 compilerOptions.strictNullChecks:true 表示更加严格的空类型检查, 开启该置上面的写法在 ts 中是不合法的。
类型举例
变量
let name: string : 给变量定义为 字符串 类型, 后续的赋值只能给 name 赋值为 字符创 类型否则报错。
可以写为: let name:string = '托尼'
函数参数, 函数返回值
function sum(a: number, b: number): number {
return a + b
}
函数参数的类型约束就直接写在 参数后面,返回值写在 大括号前, 上面的代码表示 参数 a 必须传递 number 类型,b 同上, 函数返回的结果必须是 number 类型, 在使用该函数就必须遵守这个 参数的规则不然就报错
并且使用该函数必须传递两个参数,不然也会报错
其它常用类型
联合类型
let name: string | undefined;
表示 name 可以是 string 类型,也可以是 undefined 类型
let name: string | undefined;
if(typeof name === 'string'){
//代码执行到这里 ts 就认为 name 一定是 string 类型
}
这个叫做 ts 的类型保护
void 类型
通常用于约束函数的返回值, 表示该函数没有任何返回值。
never 类型
通常用于约束函数的返回值, 表示该函数永远不可能结束
//该函数永远 不可能结束
function s ():never {
where(true){
}
}
//该函数永远 不可能结束
function err(): never {
throw new Error('错误')
}
字面量类型
let str:'A'; 表示 str 只能赋值为 'A'
let obj:{
name: string
age: number
}
表示 obj 是能是带有 name 和 age 的属性名的对象
元祖类型(Tuple)
一个固定长度的数组, 并且数组中每一项的类型确定。
let tu: [string, number]; //表示 tu 只能是两项 第一项必须是 string 第二项必须是 number
any类型
any 类型可以绕过类型检查, 这就和平时写 js 没有差异。
any 类型可以赋值给其他类型
let str: any = '123'
let num: number = str
在 ts 中是合法的, 但是这就导致了隐患, 所以不推荐这样使用。
引用类型
数组
这里我想创建一个 number 的数组: 改数组的每一项为 number 类型
let nums: Array<number>;
let nums: number[]; 这是上面写法的 语法糖
都表示为创建一个 number 类型的数组
对象
let obj: object obj 可以有任何的属性, 所以用这种方式约束对象不常用, 在后面的文章中会介绍有可以约束 对象有哪些属性的手段
ts 在很多场景中可以完成类型推导
ts 能只能的推导运算结果是什么类型
function sum(a: number, b: number) {
return a + b
}
let a = sum(1, 2)
不给这个 sum 函数指定返回类型, ts 能够只能的判断出 sum 函数会返回 number 类型,所以 a 变量也是一个 number 类型
在 vscode 编辑器中, 我怎么知道有没有推导成功看下图:
有这个存在的时候 就说明 ts 就无法推导出该类型到底是什么,这里就需要手动约束了。如果没有推导出来就默认为
类型别名
类型别名 像是一种 提取公共代码
let user:{
name: string
age: number
gender: '女' | '男'
}
// 假如有这样一个函数, 会返回 上面对象类型的数组, 根据上面的知识可以这样写
function getUsers():{
name: string
age: number
gender: '女' | '男'
}[]{
}
上面的写法 很明显不够优雅 也会存在代码冗余
所以这里可以使用类型别名, 把共同的代码提取出来去一个名字。
type userType = {
name: string
age: number
gender: '女' | '男'
}
let user:userType
function getUsers():userType[]{}
约束函数
//第一种
type Condition = (item: number, index: number): boolean
//第二种
type Condition = {
(item: number, index: number): boolean
}
类似继承的写法
type a = {
a:number
}
type b = {
b:string
}
type c = {
c:boolean
} & a & b
类型别名可以定义为任何类型, 要学会举一反三。
函数的相关约束
函数重载
在函数实现之前, 对函数调用的多种情况进行声明。
举例
现在有一个函数,该函数有两个参数, 当这两个参数全为 number 类型, 或者全为 string 类型 时进行不同的操作。
type Arg = number | string
function combin(a: Arg, b: Arg): Arg{
if(typeof a === 'number' && typeof b === 'number'){
return a * b
}else if (typeof a === 'string' && typeof b === 'string') {
return a + b
}else{
throw new Error('a 和 b 必须是相同类型。')
}
}
这里假如有变量使用了这个函数
const n = combin(1,2)
此时 n 的类型 ts 判断为不是 number | string 但是我知道这个 n 一定是 number, 所以上面的函数缺少了 函数重载
加上 函数重载
type Arg = number | string
//============================================
function combin(a: number, n: number): number
function combin(a: string, n: string): string
//============================================
function combin(a: Arg, b: Arg): Arg {
if (typeof a === 'number' && typeof b === 'number') {
return a * b
} else if (typeof a === 'string' && typeof b === 'string') {
return a + b
} else {
throw new Error('a 和 b 必须是相同类型。')
}
}
const n = combin(1, 2)
这就很明确的告诉 ts 传递什么参数, 返回什么类型。 此时 n 就一定是 number。
可选参数
可以在某些参数后加上 ?, 表示该参数可以不用传递。
注意: 可选参数只能出现在参数末尾。
function ao(a: number, b?: number) {
return a + (b || 0);
}
总结
ts 是一门可选的类型检查系统, 它不会存在我们的编译结果中, 它只在开发的过程中提升我们代码的健壮性, 从而减少代码隐藏的风险, 至于你使不使用 ts 全看你心情.